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; }
GAULFUNC int ga_sa( population *pop, entity *initial, const int max_iterations ) { int iteration=0; /* Current iteration number. */ entity *putative; /* Current solution. */ entity *best; /* Current solution. */ entity *tmp; /* Used to swap working solutions. */ /* Checks. */ if (!pop) die("NULL pointer to population structure passed."); if (!pop->evaluate) die("Population's evaluation callback is undefined."); if (!pop->mutate) die("Population's mutation callback is undefined."); if (!pop->sa_params) die("ga_population_set_sa_params(), or similar, must be used prior to ga_sa()."); /* Prepare working entities. */ putative = ga_get_free_entity(pop); best = ga_get_free_entity(pop); /* Do we need to generate a random starting solution? */ if (!initial) { plog(LOG_VERBOSE, "Will perform simulated annealling with random starting solution."); initial = ga_get_free_entity(pop); ga_entity_seed(pop, best); } else { plog(LOG_VERBOSE, "Will perform simulated annealling with specified starting solution."); ga_entity_copy(pop, best, initial); } /* * Ensure that initial solution is scored. */ if (best->fitness==GA_MIN_FITNESS) pop->evaluate(pop, best); plog( LOG_VERBOSE, "Prior to the first iteration, the current solution has fitness score of %f", best->fitness ); /* * Do all the iterations: * * Stop when (a) max_iterations reached, or * (b) "pop->iteration_hook" returns FALSE. */ pop->sa_params->temperature = pop->sa_params->initial_temp; while ( (pop->iteration_hook?pop->iteration_hook(iteration, best):TRUE) && iteration<max_iterations ) { iteration++; if (pop->sa_params->temp_freq == -1) { pop->sa_params->temperature = pop->sa_params->initial_temp + ((double)iteration/max_iterations) * (pop->sa_params->final_temp-pop->sa_params->initial_temp); } else { if ( pop->sa_params->temperature > pop->sa_params->final_temp && iteration%pop->sa_params->temp_freq == 0 ) { pop->sa_params->temperature -= pop->sa_params->temp_step; } } /* * Generate and score a new solution. */ pop->mutate(pop, best, putative); pop->evaluate(pop, putative); /* * Use the acceptance criterion to decide whether this new solution should * be selected or discarded. */ if ( pop->sa_params->sa_accept(pop, best, putative) ) { tmp = best; best = putative; putative = tmp; } /* * Save the current best solution in the initial entity, if this * is now the best found so far. */ if ( initial->fitness<best->fitness ) { ga_entity_blank(pop, initial); ga_entity_copy(pop, initial, best); } /* * Use the iteration callback. */ plog( LOG_VERBOSE, "After iteration %d, the current solution has fitness score of %f", iteration, best->fitness ); } /* Iteration loop. */ /* * Cleanup. */ ga_entity_dereference(pop, best); ga_entity_dereference(pop, putative); return iteration; }
GAULFUNC int ga_random_search( population *pop, entity *best, const int max_iterations ) { int iteration=0; /* Current iteration number. */ entity *putative; /* Current solution. */ entity *tmp; /* Used to swap entities. */ /* Checks. */ if (!pop) die("NULL pointer to population structure passed."); if (pop->size < 1) die("Population is empty."); if (!pop->evaluate) die("Population's evaluation callback is undefined."); if (!pop->seed) die("Population's seed callback is undefined."); /* Prepare working entity. */ putative = ga_get_free_entity(pop); /* Do we need to generate a random starting solution? */ if (!best) { plog(LOG_VERBOSE, "Will perform random search with random starting solution."); best = ga_get_free_entity(pop); ga_entity_seed(pop, best); } else { plog(LOG_VERBOSE, "Will perform random search with specified starting solution."); } /* * Ensure that initial solution is scored. */ if (best->fitness==GA_MIN_FITNESS) pop->evaluate(pop, best); plog( LOG_VERBOSE, "Prior to the first iteration, the current solution has fitness score of %f", best->fitness ); /* * Do all the iterations: * * Stop when (a) max_iterations reached, or * (b) "pop->iteration_hook" returns FALSE. */ while ( (pop->iteration_hook?pop->iteration_hook(iteration, best):TRUE) && iteration<max_iterations ) { iteration++; /* * Generate and score a new solution. */ ga_entity_blank(pop, putative); pop->seed(pop, putative); pop->evaluate(pop, putative); /* * Decide whether this new solution should be selected or discarded based * on the relative fitnesses. */ if ( putative->fitness > best->fitness ) { tmp = best; best = putative; putative = tmp; } /* * Use the iteration callback. */ plog( LOG_VERBOSE, "After iteration %d, the current solution has fitness score of %f", iteration, best->fitness ); } /* Iteration loop. */ /* * Cleanup. */ ga_entity_dereference(pop, putative); return iteration; }
GAULFUNC int ga_search( population *pop, entity *best) { int iteration=0; /* Current iteration number. */ entity *putative; /* Current solution. */ entity *tmp; /* Used to swap entities. */ int enumeration=0; /* Enumeration index. */ boolean finished=FALSE; /* Whether search is complete. */ /* Checks. */ if (!pop) die("NULL pointer to population structure passed."); if (!pop->evaluate) die("Population's evaluation callback is undefined."); if (!pop->search_params) die("ga_population_set_search_params(), or similar, must be used prior to ga_search()."); if (!pop->search_params->scan_chromosome) die("Population's chromosome scan callback is undefined."); /* Prepare working entity. */ putative = ga_get_free_entity(pop); plog(LOG_VERBOSE, "Will perform systematic search."); /* Do we need to allocate starting solution? */ if (!best) { best = ga_get_free_entity(pop); ga_entity_seed(pop, best); } /* * Ensure that initial solution is scored. */ if (best->fitness==GA_MIN_FITNESS) pop->evaluate(pop, best); /* * Prepare internal data for the enumeration algorithm. */ pop->search_params->chromosome_state = 0; pop->search_params->allele_state = 0; /* * Do all the iterations: * * Stop when (a) All enumerations performed or * (b) "pop->iteration_hook" returns FALSE. */ while ( (pop->iteration_hook?pop->iteration_hook(iteration, best):TRUE) && finished == FALSE ) { iteration++; /* * Generate and score a new solution. */ ga_entity_blank(pop, putative); finished = pop->search_params->scan_chromosome(pop, putative, enumeration); pop->evaluate(pop, putative); /* * Decide whether this new solution should be selected or discarded based * on the relative fitnesses. */ if ( putative->fitness > best->fitness ) { tmp = best; best = putative; putative = tmp; } /* * Use the iteration callback. */ plog( LOG_VERBOSE, "After iteration %d, the current solution has fitness score of %f", iteration, best->fitness ); } /* Iteration loop. */ /* * Cleanup. */ ga_entity_dereference(pop, putative); return iteration; }
GAULFUNC int ga_tabu( population *pop, entity *initial, const int max_iterations ) { int iteration=0; /* Current iteration number. */ int i, j; /* Index into putative solution array. */ entity *best; /* Current best solution. */ entity **putative; /* Current working solutions. */ entity *tmp; /* Used to swap working solutions. */ entity **tabu_list; /* Tabu list. */ int tabu_list_pos=0; /* Index into the tabu list. */ /* Checks. */ if (!pop) die("NULL pointer to population structure passed."); if (!pop->evaluate) die("Population's evaluation callback is undefined."); if (!pop->mutate) die("Population's mutation callback is undefined."); if (!pop->rank) die("Population's ranking callback is undefined."); if (!pop->tabu_params) die("ga_population_set_tabu_params(), or similar, must be used prior to ga_tabu()."); if (!pop->tabu_params->tabu_accept) die("Population's tabu acceptance callback is undefined."); /* Prepare working entities. */ best = ga_get_free_entity(pop); /* The best solution so far. */ if ( !(putative = s_malloc(sizeof(entity *)*pop->tabu_params->search_count)) ) die("Unable to allocate memory"); for (i=0; i<pop->tabu_params->search_count; i++) { putative[i] = ga_get_free_entity(pop); /* The 'working' solutions. */ } /* Allocate and clear an array for the tabu list. */ if ( !(tabu_list = s_malloc(sizeof(vpointer)*pop->tabu_params->list_length)) ) die("Unable to allocate memory"); for (i=0; i<pop->tabu_params->list_length; i++) { tabu_list[i] = NULL; } /* Do we need to generate a random starting solution? */ if (!initial) { plog(LOG_VERBOSE, "Will perform tabu-search with random starting solution."); initial = ga_get_free_entity(pop); ga_entity_seed(pop, best); } else { plog(LOG_VERBOSE, "Will perform tabu-search with specified starting solution."); ga_entity_copy(pop, best, initial); } /* * Ensure that initial solution is scored. */ if (best->fitness==GA_MIN_FITNESS) pop->evaluate(pop, best); plog( LOG_VERBOSE, "Prior to the first iteration, the current solution has fitness score of %f", best->fitness ); /* * Do all the iterations: * * Stop when (a) max_iterations reached, or * (b) "pop->iteration_hook" returns FALSE. */ while ( (pop->iteration_hook?pop->iteration_hook(iteration, best):TRUE) && iteration<max_iterations ) { iteration++; /* * Generate and score new solutions. */ for (i=0; i<pop->tabu_params->search_count; i++) { pop->mutate(pop, best, putative[i]); pop->evaluate(pop, putative[i]); } /* * Sort new solutions (putative[0] will have highest rank). * We assume that there are only a small(ish) number of * solutions and, therefore, a simple bubble sort is adequate. */ for (i=1; i<pop->tabu_params->search_count; i++) { for (j=pop->tabu_params->search_count-1; j>=i; j--) { if ( pop->rank(pop, putative[j], pop, putative[j-1]) > 0 ) { /* Perform a swap. */ tmp = putative[j]; putative[j] = putative[j-1]; putative[j-1] = tmp; } } } /* * Save best solution if it is an improvement, otherwise * select the best non-tabu solution (if any). * If appropriate, update the tabu list. */ if ( pop->rank(pop, putative[0], pop, best) > 0 ) { tmp = best; best = putative[0]; putative[0] = tmp; if (tabu_list[tabu_list_pos] == NULL) { tabu_list[tabu_list_pos] = ga_entity_clone(pop, best); } else { ga_entity_blank(pop, tabu_list[tabu_list_pos]); ga_entity_copy(pop, tabu_list[tabu_list_pos], best); } tabu_list_pos++; if (tabu_list_pos >= pop->tabu_params->list_length) tabu_list_pos=0; } else { if ( -1 < (j = gaul_check_tabu_list(pop, putative, tabu_list)) ) { tmp = best; best = putative[j]; putative[j] = tmp; if (tabu_list[tabu_list_pos] == NULL) { tabu_list[tabu_list_pos] = ga_entity_clone(pop, best); } else { ga_entity_blank(pop, tabu_list[tabu_list_pos]); ga_entity_copy(pop, tabu_list[tabu_list_pos], best); } tabu_list_pos++; if (tabu_list_pos >= pop->tabu_params->list_length) tabu_list_pos=0; } } /* * Save the current best solution in the initial entity, if this * is now the best found so far. */ if ( pop->rank(pop, best, pop, initial) > 0 ) { ga_entity_blank(pop, initial); ga_entity_copy(pop, initial, best); } /* * Use the iteration callback. */ plog( LOG_VERBOSE, "After iteration %d, the current solution has fitness score of %f", iteration, best->fitness ); } /* Iteration loop. */ /* * Cleanup. */ ga_entity_dereference(pop, best); for (i=0; i<pop->tabu_params->search_count; i++) { ga_entity_dereference(pop, putative[i]); } for (i=0; i<pop->tabu_params->list_length; i++) { if (tabu_list[i] != NULL) ga_entity_dereference(pop, tabu_list[i]); } s_free(putative); s_free(tabu_list); return iteration; }
GAULFUNC entity *ga_allele_search( population *pop, const int chromosomeid, const int point, const int min_val, const int max_val, entity *initial ) { int val; /* Current value for point. */ entity *current, *best; /* The solutions. */ /* Checks. */ /* FIXME: More checks needed. */ if ( !pop ) die("Null pointer to population structure passed."); current = ga_get_free_entity(pop); /* The 'working' solution. */ best = ga_get_free_entity(pop); /* The best solution so far. */ plog(LOG_WARNING, "ga_allele_search() is a deprecated function!"); /* Do we need to generate a random solution? */ if (initial==NULL) { plog(LOG_VERBOSE, "Will perform systematic allele search with random starting solution."); pop->seed(pop, best); } else { plog(LOG_VERBOSE, "Will perform systematic allele search."); ga_entity_copy(pop, best, initial); } /* * Copy best solution over current solution. */ ga_entity_copy(pop, current, best); best->fitness=GA_MIN_FITNESS; /* * Loop over the range of legal values. */ for (val = min_val; val < max_val; val++) { ((int *)current->chromosome[chromosomeid])[point] = val; ga_entity_clear_data(pop, current, chromosomeid); pop->evaluate(pop, current); /* * Should we keep this solution? */ if ( best->fitness < current->fitness ) { /* Copy this solution best solution. */ ga_entity_blank(pop, best); ga_entity_copy(pop, best, current); } else { /* Copy best solution over current solution. */ ga_entity_blank(pop, current); ga_entity_copy(pop, current, best); } } plog(LOG_VERBOSE, "After complete search the best solution has fitness score of %f", best->fitness ); /* * Current no longer needed. It is upto the caller to dereference the * optimum solution found. */ ga_entity_dereference(pop, current); return best; }
int ga_steepestascent_double( population *pop, entity *current, const int max_iterations ) { int iteration=0; /* Current iteration number. */ int i; /* Index into arrays. */ double *current_g; /* Current iteration gradient array. */ entity *putative; /* New solution. */ entity *tmpentity; /* Used to swap working solutions. */ double step_size; /* Current step size. */ double grms; /* Current RMS gradient. */ boolean force_terminate=FALSE; /* Force optimisation to terminate. */ /* * Checks. */ if (!pop) die("NULL pointer to population structure passed."); if (!pop->evaluate) die("Population's evaluation callback is undefined."); if (!pop->gradient_params) die("ga_population_set_gradient_params(), or similar, must be used prior to ga_gradient()."); if (!pop->gradient_params->gradient) die("Population's first derivatives callback is undefined."); /* * Prepare working entity and gradient array. */ current_g = s_malloc(sizeof(double)*pop->len_chromosomes); putative = ga_get_free_entity(pop); /* Do we need to generate a random starting solution? */ if (current==NULL) { plog(LOG_VERBOSE, "Will perform gradient search with random starting solution."); current = ga_get_free_entity(pop); ga_entity_seed(pop, current); } else { plog(LOG_VERBOSE, "Will perform gradient search with specified starting solution."); } /* * Get initial fitness and derivatives. */ pop->evaluate(pop, current); grms = pop->gradient_params->gradient(pop, current, (double *)current->chromosome[0], current_g); plog( LOG_VERBOSE, "Prior to the first iteration, the current solution has fitness score of %f and a RMS gradient of %f", current->fitness, grms ); /* * Adjust step size based on gradient. * This scales the step size according to the initial gradient so that the * calculation doesn't blow-up completely. */ /* step_size=(pop->len_chromosomes*pop->gradient_params->step_size)/grms;*/ step_size=pop->gradient_params->step_size; /* * Do all the iterations: * * Stop when (a) max_iterations reached, or * (b) "pop->iteration_hook" returns FALSE. * The iteration hook could evaluate the RMS gradient, or the maximum component * of the gradient, or any other termination criteria that may be desirable. */ while ( force_terminate==FALSE && (pop->iteration_hook?pop->iteration_hook(iteration, current):TRUE) && iteration<max_iterations ) { iteration++; for( i=0; i<pop->len_chromosomes; i++ ) ((double *)putative->chromosome[0])[i]=((double *)current->chromosome[0])[i]+step_size*current_g[i]; pop->evaluate(pop, putative); #if GA_DEBUG>2 printf("DEBUG: current_d = %f %f %f %f\n", current_d[0], current_d[1], current_d[2], current_d[3]); printf("DEBUG: current_g = %f %f %f %f grms = %f\n", current_g[0], current_g[1], current_g[2], current_g[3], grms); printf("DEBUG: putative_d = %f %f %f %f fitness = %f\n", putative_d[0], putative_d[1], putative_d[2], putative_d[3], putative->fitness); #endif if ( current->fitness > putative->fitness ) { /* New solution is worse. */ do { step_size *= pop->gradient_params->alpha; /*printf("DEBUG: step_size = %e\n", step_size);*/ for( i=0; i<pop->len_chromosomes; i++ ) ((double *)putative->chromosome[0])[i]=((double *)current->chromosome[0])[i]+step_size*current_g[i]; pop->evaluate(pop, putative); } while( current->fitness > putative->fitness && step_size > ApproxZero); if (step_size <= ApproxZero && grms <= ApproxZero) force_terminate=TRUE; } else { /* New solution is an improvement. */ step_size *= pop->gradient_params->beta; #if GA_DEBUG>2 printf("DEBUG: step_size = %e\n", step_size); #endif } /* Store improved solution. */ tmpentity = current; current = putative; putative = tmpentity; grms = pop->gradient_params->gradient(pop, current, (double *)current->chromosome[0], current_g); /* * Use the iteration callback. */ plog( LOG_VERBOSE, "After iteration %d, the current solution has fitness score of %f and RMS gradient of %f (step_size = %f)", iteration, current->fitness, grms, step_size ); } /* Iteration loop. */ /* * Cleanup. */ ga_entity_dereference(pop, putative); return iteration; }
GAULFUNC int ga_random_ascent_hillclimbing( population *pop, entity *best, const int max_iterations ) { int iteration=0; /* Current iteration number. */ entity *putative; /* Current solution. */ entity *tmp; /* Used to swap working solutions. */ int chromo_id; /* Chromosome number. */ int allele_id; /* Allele number. */ /* Checks. */ if (!pop) die("NULL pointer to population structure passed."); if (!pop->evaluate) die("Population's evaluation callback is undefined."); if (!pop->climbing_params) die("ga_population_set_hillclimbing_params(), or similar, must be used prior to ga_random_ascent_hillclimbing()."); if (!pop->climbing_params->mutate_allele) die("Population's allele mutation callback is undefined."); /* Prepare working entity. */ putative = ga_get_free_entity(pop); /* Do we need to generate a random starting solution? */ if (!best) { plog(LOG_VERBOSE, "Will perform hill climbing with random starting solution."); best = ga_get_free_entity(pop); ga_entity_seed(pop, best); } else { plog(LOG_VERBOSE, "Will perform hill climbing with specified starting solution."); } /* * Ensure that initial solution is scored. */ if (best->fitness==GA_MIN_FITNESS) pop->evaluate(pop, best); plog( LOG_VERBOSE, "Prior to the first iteration, the current solution has fitness score of %f", best->fitness ); /* * Do all the iterations: * * Stop when (a) max_iterations reached, or * (b) "pop->iteration_hook" returns FALSE. */ while ( (pop->iteration_hook?pop->iteration_hook(iteration, best):TRUE) && iteration<max_iterations ) { iteration++; /* * Generate and score a new solution. */ chromo_id = random_int(pop->num_chromosomes); allele_id = random_int(pop->len_chromosomes); pop->climbing_params->mutate_allele(pop, best, putative, chromo_id, allele_id); pop->mutate(pop, best, putative); pop->evaluate(pop, putative); /* * Decide whether this new solution should be selected or discarded based * on the relative fitnesses. */ if ( putative->fitness > best->fitness ) { tmp = best; best = putative; putative = tmp; } /* * Use the iteration callback. */ plog( LOG_VERBOSE, "After iteration %d, the current solution has fitness score of %f", iteration, best->fitness ); } /* Iteration loop. */ /* * Cleanup. */ ga_entity_dereference(pop, putative); return iteration; }