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_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_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; }
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; }