2
2
import numpy as np
3
3
4
4
# Parameters
5
- N_POPULATION = 100 # Population size
5
+ N_POPULATION = 100 # Population size
6
6
N_GENERATIONS = 500 # Maximum number of generations
7
- N_SELECTED = 50 # Number of parents selected for the next generation
7
+ N_SELECTED = 50 # Number of parents selected for the next generation
8
8
MUTATION_PROBABILITY = 0.1 # Mutation probability
9
9
CROSSOVER_RATE = 0.8 # Probability of crossover
10
10
SEARCH_SPACE = (- 10 , 10 ) # Search space for the variables
11
11
12
+
12
13
# Genetic Algorithm for Function Optimization
13
14
class GeneticAlgorithm :
14
- def __init__ (self , function , bounds , population_size , generations , mutation_prob , crossover_rate , maximize = True ):
15
+ def __init__ (
16
+ self ,
17
+ function ,
18
+ bounds ,
19
+ population_size ,
20
+ generations ,
21
+ mutation_prob ,
22
+ crossover_rate ,
23
+ maximize = True ,
24
+ ):
15
25
self .function = function # Target function to optimize
16
26
self .bounds = bounds # Search space bounds (for each variable)
17
27
self .population_size = population_size
@@ -20,27 +30,33 @@ def __init__(self, function, bounds, population_size, generations, mutation_prob
20
30
self .crossover_rate = crossover_rate
21
31
self .maximize = maximize
22
32
self .dim = len (bounds ) # Dimensionality of the function (number of variables)
23
-
33
+
24
34
# Initialize population
25
35
self .population = self .initialize_population ()
26
-
36
+
27
37
def initialize_population (self ):
28
38
# Generate random initial population within the search space
29
- return [np .random .uniform (low = self .bounds [i ][0 ], high = self .bounds [i ][1 ], size = self .dim )
30
- for i in range (self .population_size )]
31
-
39
+ return [
40
+ np .random .uniform (
41
+ low = self .bounds [i ][0 ], high = self .bounds [i ][1 ], size = self .dim
42
+ )
43
+ for i in range (self .population_size )
44
+ ]
45
+
32
46
def fitness (self , individual ):
33
47
# Calculate the fitness value (function value)
34
48
value = self .function (* individual )
35
49
return value if self .maximize else - value # If minimizing, invert the fitness
36
-
50
+
37
51
def select_parents (self ):
38
52
# Rank individuals based on fitness and select top individuals for mating
39
- scores = [(individual , self .fitness (individual )) for individual in self .population ]
53
+ scores = [
54
+ (individual , self .fitness (individual )) for individual in self .population
55
+ ]
40
56
scores .sort (key = lambda x : x [1 ], reverse = True )
41
57
selected = [ind for ind , _ in scores [:N_SELECTED ]]
42
58
return selected
43
-
59
+
44
60
def crossover (self , parent1 , parent2 ):
45
61
# Perform uniform crossover
46
62
if random .random () < self .crossover_rate :
@@ -49,14 +65,14 @@ def crossover(self, parent1, parent2):
49
65
child2 = np .concatenate ((parent2 [:cross_point ], parent1 [cross_point :]))
50
66
return child1 , child2
51
67
return parent1 , parent2
52
-
68
+
53
69
def mutate (self , individual ):
54
70
# Apply mutation to an individual with some probability
55
71
for i in range (self .dim ):
56
72
if random .random () < self .mutation_prob :
57
73
individual [i ] = np .random .uniform (self .bounds [i ][0 ], self .bounds [i ][1 ])
58
74
return individual
59
-
75
+
60
76
def evolve (self ):
61
77
for generation in range (self .generations ):
62
78
# Select parents based on fitness
@@ -71,15 +87,17 @@ def evolve(self):
71
87
next_generation .append (self .mutate (child2 ))
72
88
73
89
# Ensure population size remains the same
74
- self .population = next_generation [:self .population_size ]
90
+ self .population = next_generation [: self .population_size ]
75
91
76
92
# Track the best solution so far
77
93
best_individual = max (self .population , key = self .fitness )
78
94
best_fitness = self .fitness (best_individual )
79
-
95
+
80
96
if generation % 10 == 0 :
81
- print (f"Generation { generation } : Best Fitness = { best_fitness } , Best Individual = { best_individual } " )
82
-
97
+ print (
98
+ f"Generation { generation } : Best Fitness = { best_fitness } , Best Individual = { best_individual } "
99
+ )
100
+
83
101
# Return the best individual found
84
102
return max (self .population , key = self .fitness )
85
103
@@ -88,6 +106,7 @@ def evolve(self):
88
106
def target_function (x , y ):
89
107
return x ** 2 + y ** 2 # Example: simple parabolic surface (minimization)
90
108
109
+
91
110
# Set bounds for the variables (x, y)
92
111
bounds = [(- 10 , 10 ), (- 10 , 10 )] # Both x and y range from -10 to 10
93
112
@@ -99,7 +118,7 @@ def target_function(x, y):
99
118
generations = N_GENERATIONS ,
100
119
mutation_prob = MUTATION_PROBABILITY ,
101
120
crossover_rate = CROSSOVER_RATE ,
102
- maximize = False # Set to False for minimization
121
+ maximize = False , # Set to False for minimization
103
122
)
104
123
105
124
# Run the genetic algorithm and find the optimal solution
0 commit comments