2
2
import random
3
3
from concurrent .futures import ThreadPoolExecutor
4
4
5
+
5
6
# Parameters
6
7
N_POPULATION = 100 # Population size
7
8
N_GENERATIONS = 500 # Maximum number of generations
10
11
CROSSOVER_RATE = 0.8 # Probability of crossover
11
12
SEARCH_SPACE = (- 10 , 10 ) # Search space for the variables
12
13
14
+
13
15
# Random number generator
14
16
rng = np .random .default_rng ()
15
17
@@ -25,6 +27,7 @@ def __init__(
25
27
crossover_rate ,
26
28
maximize = True ,
27
29
):
30
+
28
31
self .function = function # Target function to optimize
29
32
self .bounds = bounds # Search space bounds (for each variable)
30
33
self .population_size = population_size
@@ -44,16 +47,19 @@ def initialize_population(self):
44
47
for i in range (self .population_size )
45
48
]
46
49
50
+
47
51
def fitness (self , individual ):
48
52
# Calculate the fitness value (function value)
49
53
value = self .function (* individual )
50
54
return value if self .maximize else - value # If minimizing, invert the fitness
51
55
56
+
52
57
def select_parents (self , population_score ):
53
58
# Select top N_SELECTED parents based on fitness
54
59
population_score .sort (key = lambda x : x [1 ], reverse = True )
55
60
return [ind for ind , _ in population_score [:N_SELECTED ]]
56
61
62
+
57
63
def crossover (self , parent1 , parent2 ):
58
64
# Perform uniform crossover
59
65
if random .random () < self .crossover_rate :
@@ -63,20 +69,23 @@ def crossover(self, parent1, parent2):
63
69
return child1 , child2
64
70
return parent1 , parent2
65
71
72
+
66
73
def mutate (self , individual ):
67
74
# Apply mutation to an individual using the new random generator
68
75
for i in range (self .dim ):
69
76
if random .random () < self .mutation_prob :
70
77
individual [i ] = rng .uniform (self .bounds [i ][0 ], self .bounds [i ][1 ])
71
78
return individual
72
79
80
+
73
81
def evaluate_population (self ):
74
82
# Multithreaded evaluation of population fitness
75
83
with ThreadPoolExecutor () as executor :
76
84
return list (
77
85
executor .map (lambda ind : (ind , self .fitness (ind )), self .population )
78
86
)
79
87
88
+
80
89
def evolve (self ):
81
90
for generation in range (self .generations ):
82
91
# Evaluate population fitness (multithreaded)
@@ -114,6 +123,7 @@ def target_function(x, y):
114
123
# Set bounds for the variables (x, y)
115
124
bounds = [(- 10 , 10 ), (- 10 , 10 )] # Both x and y range from -10 to 10
116
125
126
+
117
127
# Instantiate and run the genetic algorithm
118
128
ga = GeneticAlgorithm (
119
129
function = target_function ,
@@ -125,6 +135,7 @@ def target_function(x, y):
125
135
maximize = False , # Minimize the function
126
136
)
127
137
138
+
128
139
best_solution = ga .evolve ()
129
140
print (f"Best solution found: { best_solution } " )
130
141
print (f"Best fitness (minimum value of function): { target_function (* best_solution )} " )
0 commit comments