Skip to content

Commit 1873f2f

Browse files
committed
Update genetic_algorithm_optimization.py
1 parent 3a654c5 commit 1873f2f

File tree

1 file changed

+38
-19
lines changed

1 file changed

+38
-19
lines changed

genetic_algorithm/genetic_algorithm_optimization.py

+38-19
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
import numpy as np
22
from typing import Callable, List, Tuple
33

4-
54
class GeneticAlgorithmOptimizer:
65
def __init__(
76
self,
8-
objective_function: Callable[..., float], # The function that returns the value to be minimized
9-
variable_bounds: List[Tuple[float, float]], # List of tuples specifying the bounds for each variable
7+
objective_function: Callable[..., float],
8+
variable_bounds: List[Tuple[float, float]],
109
population_size: int = 100,
1110
max_generations: int = 500,
1211
crossover_probability: float = 0.9,
@@ -27,7 +26,10 @@ def generate_initial_population(self) -> np.ndarray:
2726
"""
2827
Generate a population of random solutions within the given variable bounds.
2928
30-
>>> optimizer = GeneticAlgorithmOptimizer(objective_function=lambda x: x**2, variable_bounds=[(-10, 10)])
29+
>>> optimizer = GeneticAlgorithmOptimizer(
30+
... objective_function=lambda x: x**2,
31+
... variable_bounds=[(-10, 10)]
32+
... )
3133
>>> population = optimizer.generate_initial_population()
3234
>>> population.shape == (optimizer.population_size, optimizer.num_variables)
3335
True
@@ -42,19 +44,27 @@ def evaluate_fitness(self, individual: List[float]) -> float:
4244
"""
4345
Evaluate the fitness of an individual by computing the value of the objective function.
4446
45-
>>> optimizer = GeneticAlgorithmOptimizer(objective_function=lambda x: x**2, variable_bounds=[(-10, 10)])
47+
>>> optimizer = GeneticAlgorithmOptimizer(
48+
... objective_function=lambda x: x**2,
49+
... variable_bounds=[(-10, 10)]
50+
... )
4651
>>> optimizer.evaluate_fitness([2])
4752
4
4853
>>> optimizer.evaluate_fitness([0])
4954
0
5055
"""
5156
return self.objective_function(*individual)
5257

53-
def select_parent(self, population: np.ndarray, fitness_values: np.ndarray) -> np.ndarray:
58+
def select_parent(
59+
self, population: np.ndarray, fitness_values: np.ndarray
60+
) -> np.ndarray:
5461
"""
5562
Select a parent using tournament selection based on fitness values.
5663
57-
>>> optimizer = GeneticAlgorithmOptimizer(objective_function=lambda x: x**2, variable_bounds=[(-10, 10)])
64+
>>> optimizer = GeneticAlgorithmOptimizer(
65+
... objective_function=lambda x: x**2,
66+
... variable_bounds=[(-10, 10)]
67+
... )
5868
>>> population = optimizer.generate_initial_population()
5969
>>> fitness_values = np.array([optimizer.evaluate_fitness(ind) for ind in population])
6070
>>> parent = optimizer.select_parent(population, fitness_values)
@@ -66,19 +76,25 @@ def select_parent(self, population: np.ndarray, fitness_values: np.ndarray) -> n
6676
)
6777
return population[selected_indices[np.argmin(fitness_values[selected_indices])]]
6878

69-
def perform_crossover(self, parent1: np.ndarray, parent2: np.ndarray) -> Tuple[np.ndarray, np.ndarray]:
79+
def perform_crossover(
80+
self, parent1: np.ndarray, parent2: np.ndarray
81+
) -> Tuple[np.ndarray, np.ndarray]:
7082
"""
71-
Perform one-point crossover between two parents to create offspring. Skip crossover for single-variable functions.
83+
Perform one-point crossover between two parents to create offspring.
84+
Skip crossover for single-variable functions.
7285
73-
>>> optimizer = GeneticAlgorithmOptimizer(objective_function=lambda x: x**2, variable_bounds=[(-10, 10)])
86+
>>> optimizer = GeneticAlgorithmOptimizer(
87+
... objective_function=lambda x: x**2,
88+
... variable_bounds=[(-10, 10)]
89+
... )
7490
>>> parent1 = [1]
7591
>>> parent2 = [2]
7692
>>> child1, child2 = optimizer.perform_crossover(parent1, parent2)
7793
>>> child1 == parent1 and child2 == parent2
7894
True
7995
"""
8096
if self.num_variables == 1:
81-
return parent1, parent2 # No crossover needed for single-variable functions
97+
return parent1, parent2
8298

8399
if self.rng.random() < self.crossover_probability:
84100
crossover_point = self.rng.integers(1, self.num_variables)
@@ -91,7 +107,10 @@ def apply_mutation(self, individual: np.ndarray) -> np.ndarray:
91107
"""
92108
Apply mutation to an individual based on the mutation probability.
93109
94-
>>> optimizer = GeneticAlgorithmOptimizer(objective_function=lambda x: x**2, variable_bounds=[(-10, 10)])
110+
>>> optimizer = GeneticAlgorithmOptimizer(
111+
... objective_function=lambda x: x**2,
112+
... variable_bounds=[(-10, 10)]
113+
... )
95114
>>> individual = [1]
96115
>>> mutated_individual = optimizer.apply_mutation(individual.copy())
97116
>>> len(mutated_individual) == len(individual)
@@ -100,7 +119,8 @@ def apply_mutation(self, individual: np.ndarray) -> np.ndarray:
100119
if self.rng.random() < self.mutation_probability:
101120
mutation_index = self.rng.integers(0, self.num_variables)
102121
individual[mutation_index] = self.rng.uniform(
103-
self.variable_bounds[mutation_index, 0], self.variable_bounds[mutation_index, 1]
122+
self.variable_bounds[mutation_index, 0],
123+
self.variable_bounds[mutation_index, 1]
104124
)
105125
return individual
106126

@@ -138,9 +158,7 @@ def optimize(self) -> Tuple[np.ndarray, float]:
138158

139159
return best_solution, best_fitness_value
140160

141-
142161
if __name__ == "__main__":
143-
# Define the function to optimize
144162
def objective_function(x: float, y: float) -> float:
145163
"""
146164
Example objective function to minimize x^2 + y^2
@@ -152,13 +170,14 @@ def objective_function(x: float, y: float) -> float:
152170
>>> objective_function(-3, -4)
153171
25
154172
"""
155-
return x**2 + y**2 # Example: Minimizing x^2 + y^2
173+
return x**2 + y**2
156174

157-
# Define the bounds for each variable
158175
variable_bounds: List[Tuple[float, float]] = [(-10, 10), (-10, 10)]
159176

160-
# Initialize and run the optimizer
161-
optimizer = GeneticAlgorithmOptimizer(objective_function=objective_function, variable_bounds=variable_bounds)
177+
optimizer = GeneticAlgorithmOptimizer(
178+
objective_function=objective_function,
179+
variable_bounds=variable_bounds
180+
)
162181
best_solution, best_fitness_value = optimizer.optimize()
163182

164183
print("Best Solution:", best_solution)

0 commit comments

Comments
 (0)