GAULFUNC boolean ga_sa_boltzmann_acceptance( population *pop, entity *original, entity *putative ) { return ( original->fitness < putative->fitness || random_boolean_prob(exp((putative->fitness-original->fitness) /(GA_BOLTZMANN_FACTOR*pop->sa_params->temperature))) ); }
void pingpong_mutate(population *pop, entity *mother, entity *son) { /* Checks. */ if (!mother || !son) die("Null pointer to entity structure passed"); if (random_boolean_prob(0.5)) pingpong_mutate_swap(pop, mother, son); else pingpong_mutate_shift(pop, mother, son); return; }
boolean wildfire_seed(population *pop, entity *adam) { int i, j, k; /* Map square. */ if (random_boolean()) { for(i=0; i<WILDFIRE_X_DIMENSION*WILDFIRE_Y_DIMENSION; i++) { ((int *)adam->chromosome[0])[i] = random_boolean_prob((double)WILDFIRE_CISTERNS/ ((double)WILDFIRE_X_DIMENSION*WILDFIRE_Y_DIMENSION)); } } else { for(i=0; i<WILDFIRE_X_DIMENSION*WILDFIRE_Y_DIMENSION; i++) { ((int *)adam->chromosome[0])[i] = 0; } /* Deliberately places slightly fewer cisterns than allowed. */ i = random_int(WILDFIRE_X_DIMENSION*WILDFIRE_Y_DIMENSION); j = random_int(WILDFIRE_X_DIMENSION*WILDFIRE_Y_DIMENSION); k = WILDFIRE_CISTERNS; while (k>0) { i = (i+j)%(WILDFIRE_X_DIMENSION*WILDFIRE_Y_DIMENSION); if (((int *)adam->chromosome[0])[i] == 1) { j = random_int(WILDFIRE_X_DIMENSION*WILDFIRE_Y_DIMENSION); } else { ((int *)adam->chromosome[0])[i] = 1; } k--; } } return TRUE; }
int ga_deterministiccrowding( population *pop, const int max_generations ) { int generation=0; /* Current generation number. */ int *permutation, *ordered; /* Arrays of entities. */ entity *mother, *father; /* Current entities. */ entity *son, *daughter, *entity; /* Current entities. */ int i; /* Loop variable over entities. */ double dist1, dist2; /* Genetic or phenomic distances. */ int rank; /* Rank of entity in population. */ /* Checks. */ if (!pop) die("NULL pointer to population structure passed."); if (!pop->dc_params) die("ga_population_set_deterministiccrowding_params(), or similar, must be used prior to ga_deterministiccrowding()."); if (!pop->evaluate) die("Population's evaluation callback is undefined."); if (!pop->mutate) die("Population's mutation callback is undefined."); if (!pop->crossover) die("Population's crossover callback is undefined."); if (!pop->dc_params->compare) die("Population's comparison callback is undefined."); plog(LOG_VERBOSE, "The evolution by deterministic crowding has begun!"); pop->generation = 0; /* * Score the initial population members. */ if (pop->size < pop->stable_size) gaul_population_fill(pop, pop->stable_size - pop->size); for (i=0; i<pop->size; i++) { if (pop->entity_iarray[i]->fitness == GA_MIN_FITNESS) pop->evaluate(pop, pop->entity_iarray[i]); } sort_population(pop); ga_genocide_by_fitness(pop, GA_MIN_FITNESS); /* * Prepare arrays to store permutations. */ permutation = s_malloc(sizeof(int)*pop->size); ordered = s_malloc(sizeof(int)*pop->size); for (i=0; i<pop->size;i++) ordered[i]=i; plog( LOG_VERBOSE, "Prior to the first generation, population has fitness scores between %f and %f", pop->entity_iarray[0]->fitness, pop->entity_iarray[pop->size-1]->fitness ); /* * Do all the generations: * * Stop when (a) max_generations reached, or * (b) "pop->generation_hook" returns FALSE. */ while ( (pop->generation_hook?pop->generation_hook(generation, pop):TRUE) && generation<max_generations ) { generation++; pop->generation = generation; pop->orig_size = pop->size; plog(LOG_DEBUG, "Population size is %d at start of generation %d", pop->orig_size, generation ); sort_population(pop); random_int_permutation(pop->orig_size, ordered, permutation); for ( i=0; i<pop->orig_size; i++ ) { mother = pop->entity_iarray[i]; father = pop->entity_iarray[permutation[i]]; /* * Crossover step. */ plog(LOG_VERBOSE, "Crossover between %d (rank %d fitness %f) and %d (rank %d fitness %f)", ga_get_entity_id(pop, mother), ga_get_entity_rank(pop, mother), mother->fitness, ga_get_entity_id(pop, father), ga_get_entity_rank(pop, father), father->fitness); son = ga_get_free_entity(pop); daughter = ga_get_free_entity(pop); pop->crossover(pop, mother, father, daughter, son); /* * Mutation step. */ if (random_boolean_prob(pop->mutation_ratio)) { plog(LOG_VERBOSE, "Mutation of %d (rank %d)", ga_get_entity_id(pop, daughter), ga_get_entity_rank(pop, daughter) ); entity = ga_get_free_entity(pop); pop->mutate(pop, daughter, entity); ga_entity_dereference(pop, daughter); daughter = entity; } if (random_boolean_prob(pop->mutation_ratio)) { plog(LOG_VERBOSE, "Mutation of %d (rank %d)", ga_get_entity_id(pop, son), ga_get_entity_rank(pop, son) ); entity = ga_get_free_entity(pop); pop->mutate(pop, son, entity); ga_entity_dereference(pop, son); son = entity; } /* * Apply environmental adaptations, score entities, sort entities, etc. * FIXME: Currently no adaptation. */ pop->evaluate(pop, daughter); pop->evaluate(pop, son); /* * Evaluate similarities. */ dist1 = pop->dc_params->compare(pop, mother, daughter) + pop->dc_params->compare(pop, father, son); dist2 = pop->dc_params->compare(pop, mother, son) + pop->dc_params->compare(pop, father, daughter); /* * Determine which entities will survive, and kill the others. */ if (dist1 < dist2) { rank = ga_get_entity_rank(pop, daughter); if (daughter->fitness < mother->fitness) { entity = pop->entity_iarray[i]; pop->entity_iarray[i] = pop->entity_iarray[rank]; pop->entity_iarray[rank] = entity; } ga_entity_dereference_by_rank(pop, rank); rank = ga_get_entity_rank(pop, son); if (son->fitness < father->fitness) { entity = pop->entity_iarray[permutation[i]]; pop->entity_iarray[permutation[i]] = pop->entity_iarray[rank]; pop->entity_iarray[rank] = entity; } ga_entity_dereference_by_rank(pop, rank); } else { rank = ga_get_entity_rank(pop, son); if (son->fitness < mother->fitness) { entity = pop->entity_iarray[i]; pop->entity_iarray[i] = pop->entity_iarray[rank]; pop->entity_iarray[rank] = entity; } ga_entity_dereference_by_rank(pop, rank); rank = ga_get_entity_rank(pop, daughter); if (daughter->fitness < father->fitness) { entity = pop->entity_iarray[permutation[i]]; pop->entity_iarray[permutation[i]] = pop->entity_iarray[rank]; pop->entity_iarray[rank] = entity; } ga_entity_dereference_by_rank(pop, rank); } } /* * Use callback. */ plog(LOG_VERBOSE, "After generation %d, population has fitness scores between %f and %f", generation, pop->entity_iarray[0]->fitness, pop->entity_iarray[pop->size-1]->fitness ); } /* Generation loop. */ /* * Ensure final ordering of population is correct. */ sort_population(pop); return generation; }
boolean random_boolean_prob_wrapper(double *prob) { return random_boolean_prob(*prob); }
double wildfire_simulation(int map[WILDFIRE_X_DIMENSION*WILDFIRE_Y_DIMENSION], boolean show) { int time; /* Simulation time. */ int burning[WILDFIRE_X_DIMENSION*WILDFIRE_Y_DIMENSION]; /* Map. */ int crews[WILDFIRE_X_DIMENSION*WILDFIRE_Y_DIMENSION]; /* Map. */ int num_burnt=0; /* Number of burnt squares. */ int i, j, k; /* Loop variables. */ int p; /* Selected map square. */ int dir; /* Wind direction. */ /* Start with no burnt squares. */ for(p=0; p<WILDFIRE_X_DIMENSION*WILDFIRE_Y_DIMENSION; p++) burning[p] = 0; /* Random initial wind direction. */ dir = random_int(4); /* Perform simulation. */ for(time=0; time<WILDFIRE_TIME; time++) { /* Set fire to random squares. */ for(i=0; i<WILDFIRE_FLASHPOINTS; i++) { p = random_int(WILDFIRE_X_DIMENSION*WILDFIRE_Y_DIMENSION); if (map[p] == 0 && burning[p] == 0) burning[p]=1; } /* Apply the wind direction changing. */ if (WILDFIRE_PREDICTABLE_WIND == TRUE) { if (dir==3) dir=0; else dir++; } else if ( random_boolean_prob(WILDFIRE_WIND_CHANGE_PROB) ) { dir = random_int(4); } /* Fire crews try their best. */ /* Look for fires that can spread most easily, and extinguish them. */ /* FIXME: Implement firecrews to take account of predictable winds. */ /* Currently very simple: Extinguish fires that will spread the most during this day. */ /* Firstly, assess the fires. */ switch (dir) { case 0: /* North */ for(p=0; p<WILDFIRE_X_DIMENSION*WILDFIRE_Y_DIMENSION; p++) { if (burning[p] > 0 && burning[p] < 2) { crews[p]=1; while( crews[p]<WILDFIRE_WIND_SPEED && (j=p-crews[p]*WILDFIRE_X_DIMENSION)>0 && map[j] == 0 && burning[j] == 0 ) { crews[p]++; } } else { crews[p]=0; } } break; case 1: /* East */ for(p=WILDFIRE_X_DIMENSION*WILDFIRE_Y_DIMENSION-1; p>=0; p--) { if (burning[p] > 0 && burning[p] < 2) { crews[p]=1; while( crews[p]<WILDFIRE_WIND_SPEED && (j=p+crews[p])%WILDFIRE_X_DIMENSION<(WILDFIRE_X_DIMENSION-1) && map[j] == 0 && burning[j] == 0 ) { crews[p]++; } } else { crews[p]=0; } } break; case 2: /* South */ for(p=WILDFIRE_X_DIMENSION*WILDFIRE_Y_DIMENSION-1; p>=0; p--) { if (burning[p] > 0 && burning[p] < 2) { crews[p]=1; while( crews[p]<WILDFIRE_WIND_SPEED && (j=p+crews[p]*WILDFIRE_X_DIMENSION)<(WILDFIRE_Y_DIMENSION-1) && map[j] == 0 && burning[j] == 0 ) { crews[p]++; } } else { crews[p]=0; } } break; case 3: /* West */ for(p=0; p<WILDFIRE_X_DIMENSION*WILDFIRE_Y_DIMENSION; p++) { if (burning[p] > 0 && burning[p] < 2) { crews[p]=1; while( crews[p]<WILDFIRE_WIND_SPEED && (j=p-crews[p])%WILDFIRE_X_DIMENSION>0 && map[j] == 0 && burning[j] == 0 ) { crews[p]++; } } else { crews[p]=0; } } break; } /* Assign the firecrews. */ k = WILDFIRE_CREWS; j = WILDFIRE_WIND_SPEED; while (j>0 && k>0) { for(p=0; p<WILDFIRE_X_DIMENSION*WILDFIRE_Y_DIMENSION && k>0; p++) { if (crews[p]==j) { crews[p]=-1; burning[p]=0; k--; } } j--; } /* Age fires. */ for(p=0; p<WILDFIRE_X_DIMENSION*WILDFIRE_Y_DIMENSION; p++) { if (burning[p] > 0 ) burning[p]++; } for (k=0; k<WILDFIRE_WIND_SPEED; k++) { /* Spread fires. */ switch (dir) { case 0: /* North */ for(p=0; p<WILDFIRE_X_DIMENSION*WILDFIRE_Y_DIMENSION; p++) { if (burning[p] > 0 && burning[p] < 3) { if (p>WILDFIRE_X_DIMENSION) if ( map[p-WILDFIRE_X_DIMENSION] == 0 && burning[p-WILDFIRE_X_DIMENSION] == 0 && crews[p-WILDFIRE_X_DIMENSION] != -1 ) burning[p-WILDFIRE_X_DIMENSION]=1; } } break; case 1: /* East */ for(p=WILDFIRE_X_DIMENSION*WILDFIRE_Y_DIMENSION-1; p>=0; p--) { if (burning[p] > 0 && burning[p] < 3) { if (p%WILDFIRE_X_DIMENSION<(WILDFIRE_X_DIMENSION-1)) if ( map[p+1] == 0 && burning[p+1] == 0 && crews[p+1] != -1 ) burning[p+1]=1; } } break; case 2: /* South */ for(p=WILDFIRE_X_DIMENSION*WILDFIRE_Y_DIMENSION-1; p>=0; p--) { if (burning[p] > 0 && burning[p] < 3) { if (p<WILDFIRE_X_DIMENSION*(WILDFIRE_Y_DIMENSION-1)) if ( map[p+WILDFIRE_X_DIMENSION] == 0 && burning[p+WILDFIRE_X_DIMENSION] == 0 && crews[p+WILDFIRE_X_DIMENSION] != -1 ) burning[p+WILDFIRE_X_DIMENSION]=1; } } break; case 3: /* West */ for(p=0; p<WILDFIRE_X_DIMENSION*WILDFIRE_Y_DIMENSION; p++) { if (burning[p] > 0 && burning[p] < 3) { if (p%WILDFIRE_X_DIMENSION>0) if ( map[p-1] == 0 && burning[p-1] == 0 && crews[p-1] != -1 ) burning[p-1]=1; } } break; } } } /* Count number of burnt squares. */ for(i=0; i<WILDFIRE_X_DIMENSION*WILDFIRE_Y_DIMENSION; i++) if (burning[i]!=0) num_burnt++; if (show) { printf("Map after simulation is:\n"); for (i=0; i<WILDFIRE_Y_DIMENSION; i++) { for (k=0; k<WILDFIRE_X_DIMENSION; k++) { printf( "%s ", map[i*WILDFIRE_X_DIMENSION+k]?"o": ((burning[i*WILDFIRE_X_DIMENSION+k]==0)? ((crews[i*WILDFIRE_X_DIMENSION+k]==-1)?"*":"."):"x") ); } printf("\n"); } } return num_burnt; }