|
| 1 | +""" |
| 2 | +Genetic algorithm for function optimization. |
| 3 | +
|
| 4 | +Author: kpuyam |
| 5 | +""" |
| 6 | + |
| 7 | +import random |
| 8 | +from typing import Callable, Tuple, List |
| 9 | + |
| 10 | +# Define the parameters for the genetic algorithm |
| 11 | +N_POPULATION = 100 |
| 12 | +N_SELECTED = 20 |
| 13 | +MUTATION_PROBABILITY = 0.1 |
| 14 | +NUM_GENERATIONS = 50 |
| 15 | + |
| 16 | +def evaluate(func: Callable, params: List[float]) -> float: |
| 17 | + """ |
| 18 | + Evaluate the fitness of an individual based on the provided function. |
| 19 | +
|
| 20 | + Example: |
| 21 | + >>> evaluate(lambda x, y: x ** 2 + y ** 2, [3, 4]) |
| 22 | + 25 |
| 23 | + >>> evaluate(lambda x, y: x + y, [3, 4]) |
| 24 | + 7 |
| 25 | + """ |
| 26 | + return func(*params) |
| 27 | + |
| 28 | +def crossover(parent_1: List[float], parent_2: List[float]) -> List[float]: |
| 29 | + """Perform crossover between two parents.""" |
| 30 | + crossover_point = random.randint(1, len(parent_1) - 1) |
| 31 | + child = parent_1[:crossover_point] + parent_2[crossover_point:] |
| 32 | + return child |
| 33 | + |
| 34 | +def mutate(individual: List[float], mutation_rate: float) -> List[float]: |
| 35 | + """Mutate an individual with a certain probability.""" |
| 36 | + mutated_individual = [] |
| 37 | + for gene in individual: |
| 38 | + if random.random() < mutation_rate: |
| 39 | + # Add some noise to the gene's value |
| 40 | + mutated_gene = gene + random.uniform(-0.1, 0.1) |
| 41 | + mutated_individual.append(mutated_gene) |
| 42 | + else: |
| 43 | + mutated_individual.append(gene) |
| 44 | + return mutated_individual |
| 45 | + |
| 46 | +def select(population: List[Tuple[List[float], float]], num_selected: int) -> List[List[float]]: |
| 47 | + """Select individuals based on their fitness scores.""" |
| 48 | + sorted_population = sorted(population, key=lambda x: x[1]) |
| 49 | + selected_parents = [individual[0] for individual in sorted_population[:num_selected]] |
| 50 | + return selected_parents |
| 51 | + |
| 52 | +def optimize(func: Callable, num_params: int, param_ranges: List[Tuple[float, float]], optimization_goal: str) -> Tuple[List[float], float]: |
| 53 | + """Optimize the given function using a genetic algorithm.""" |
| 54 | + # Initialize the population |
| 55 | + population = [[random.uniform(param_range[0], param_range[1]) for param_range in param_ranges] for _ in range(N_POPULATION)] |
| 56 | + |
| 57 | + # Main optimization loop |
| 58 | + for generation in range(NUM_GENERATIONS): |
| 59 | + # Evaluate the fitness of each individual in the population |
| 60 | + population_fitness = [(individual, evaluate(func, individual)) for individual in population] |
| 61 | + |
| 62 | + # Select parents for crossover |
| 63 | + selected_parents = select(population_fitness, N_SELECTED) |
| 64 | + |
| 65 | + # Generate offspring through crossover and mutation |
| 66 | + offspring = [] |
| 67 | + for i in range(N_POPULATION): |
| 68 | + parent_1 = random.choice(selected_parents) |
| 69 | + parent_2 = random.choice(selected_parents) |
| 70 | + child = crossover(parent_1, parent_2) |
| 71 | + child = mutate(child, MUTATION_PROBABILITY) |
| 72 | + offspring.append(child) |
| 73 | + |
| 74 | + # Replace the old population with the offspring |
| 75 | + population = offspring |
| 76 | + |
| 77 | + # Find the best individual in the final population |
| 78 | + best_individual, best_fitness = max(population_fitness, key=lambda x: x[1]) |
| 79 | + |
| 80 | + return best_individual, best_fitness |
| 81 | + |
| 82 | +if __name__ == "__main__": |
| 83 | + # Set random seed for reproducibility |
| 84 | + random.seed(123) |
| 85 | + |
| 86 | + # Example usage: |
| 87 | + def quadratic_function(x, y): |
| 88 | + """Example function to optimize.""" |
| 89 | + return x ** 2 + y ** 2 |
| 90 | + |
| 91 | + param_ranges = [(-10, 10), (-10, 10)] |
| 92 | + best_params, best_fitness = optimize(quadratic_function, 2, param_ranges, "minimize") |
| 93 | + print("Best parameters:", best_params) |
| 94 | + print("Best fitness:", best_fitness) |
0 commit comments