import numpy as np
import matplotlib.pyplot as plt
class Individual:
def __init__(self, chromosome_length):
self.chromosome = np.random.rand(chromosome_length) * 10 – 5 # Random values between -5 and 5
self.fitness = self.calculate_fitness()
def calculate_fitness(self):
# Example objective function: f(x) = -(x^2 – 5x + 6)
return -((self.chromosome ** 2) – (5 * self.chromosome) + 6)
def mutate(self, mutation_rate):
for i in range(len(self.chromosome)):
if np.random.rand() < mutation_rate:
self.chromosome[i] += np.random.normal(0, 1) # Gaussian mutation
def crossover(self, other):
crossover_point = np.random.randint(1, len(self.chromosome) – 1)
child1 = Individual(len(self.chromosome))
child2 = Individual(len(self.chromosome))
child1.chromosome = np.concatenate((self.chromosome[:crossover_point], other.chromosome[crossover_point:]))
child2.chromosome = np.concatenate((other.chromosome[:crossover_point], self.chromosome[crossover_point:]))
return child1, child2
class GeneticAlgorithm:
def __init__(self, population_size, chromosome_length, mutation_rate, generations):
self.population_size = population_size
self.chromosome_length = chromosome_length
self.mutation_rate = mutation_rate
self.generations = generations
self.population = [Individual(chromosome_length) for _ in range(population_size)]
self.history = []
def select_parents(self):
# Roulette wheel selection
total_fitness = sum(ind.fitness for ind in self.population)
selection_probs = [ind.fitness / total_fitness for ind in self.population]
return np.random.choice(self.population, size=2, p=selection_probs)
def evolve(self):
for generation in range(self.generations):
new_population = []
for _ in range(self.population_size // 2):
parent1, parent2 = self.select_parents()
child1, child2 = parent1.crossover(parent2)
child1.mutate(self.mutation_rate)
child2.mutate(self.mutation_rate)
new_population.extend([child1, child2])
# Keep the best individuals (elitism)
best_individuals = sorted(self.population, key=lambda ind: ind.fitness, reverse=True)[:self.population_size // 10]
new_population.extend(best_individuals)
self.population = new_population[:self.population_size]
self.history.append(max(ind.fitness for ind in self.population))
def best_solution(self):
return max(self.population, key=lambda ind: ind.fitness)
def visualize(self):
plt.figure(figsize=(10, 6))
plt.plot(range(self.generations), self.history, label=’Best Fitness’, color=’blue’)
plt.title(“Genetic Algorithm Optimization Progress”)
plt.xlabel(“Generations”)
plt.ylabel(“Fitness”)
plt.grid()
plt.legend()
plt.show()
if __name__ == “__main__”:
population_size = 100
chromosome_length = 10
mutation_rate = 0.1
generations = 50
ga = GeneticAlgorithm(population_size, chromosome_length, mutation_rate, generations)
ga.evolve()
best_individual = ga.best_solution()
print(“Best Solution:”, best_individual.chromosome)
print(“Best Fitness:”, best_individual.fitness)
ga.visualize()