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