python genetic simulator in python

To create a genetic simulator in python we will be utilizing the numpy and matplotlib libraries. The following is a general outline of the steps we will need to follow:

  1. Initialization - Create an initial population of individuals randomly. Each individual should be represented by a string of genes.

  2. Selection - Select the best-fit individuals from the population.

  3. Crossover - Create new individuals by combining genes from the best-fit individuals.

  4. Mutation - Randomly mutate some genes in the population to introduce variation.

  5. Repeat - Repeat steps 2-4 until a satisfactory solution is found or a set number of generations is reached.

Here is a sample implementation of a genetic algorithm for optimizing a function that takes two inputs(x,y) and returns a value:

main.py
import numpy as np
import matplotlib.pyplot as plt

def f(x,y):
  """
  The function to optimize
  """
  return np.sin(x) + np.cos(y)

def initialize_population(pop_size, gene_length):
  """
  Creates a population of individuals
  """
  return np.random.randint(2, size=(pop_size,gene_length))

def select_parents(population, fitness):
  """
  Select the best-fit individuals from the population
  """
  sorted_fitness = sorted(range(len(fitness)), key=lambda x: fitness[x], reverse=True)
  parents = np.empty_like(population)
  for i in range(len(parents)):
    parents[i] = population[sorted_fitness[i]]
  return parents[:len(population)//2,:], parents[len(population)//2:,:]

def crossover(parents):
  """
  Creates new individuals by combining genes from the best-fit individuals
  """
  new_pop = np.empty_like(parents)
  for i in range(parents.shape[0]):
    cross_point = np.random.randint(parents.shape[1])
    new_pop[i,:cross_point] = parents[i, :cross_point]
    new_pop[i,cross_point:] = parents[(i+1)%parents.shape[0],cross_point:]
  return new_pop

def mutate(population):
  """
  Randomly mutate some genes in the population to introduce variation
  """
  for i in range(population.shape[0]):
    mutation_point = np.random.randint(population.shape[1])
    population[i,mutation_point] = 1 - population[i,mutation_point]
  return population

# Parameters
pop_size = 50
gene_length = 20
num_generations = 500
mutation_prob = 0.05

# Initialization
population = initialize_population(pop_size, gene_length)
fitness = np.empty(pop_size)

# Let's evolve!
for generation in range(num_generations):

  # Evaluate Fitness
  for i in range(pop_size):
    genes = population[i,:]
    x = (np.sum(2**np.arange(gene_length)*genes[:gene_length//2])/sum(2**np.arange(gene_length//2)))
    y = (np.sum(2**np.arange(gene_length)*genes[gene_length//2:])/sum(2**np.arange(gene_length//2)))
    fitness[i] = f(x,y)

  # Visualize the best result
  index = np.argmax(fitness)
  best_genes = population[index,:]
  x = (np.sum(2**np.arange(gene_length)*best_genes[:gene_length//2])/sum(2**np.arange(gene_length//2)))
  y = (np.sum(2**np.arange(gene_length)*best_genes[gene_length//2:])/sum(2**np.arange(gene_length//2)))
  if generation % 50 == 0:
      print(f'{generation} Best Genes: {best_genes} Best Fitness: {fitness[index]}')
      print(f'Result: f({round(x,4)}, {round(y,4)}) = {round(fitness[index],4)}')
  
  # Selection
  parents_a, parents_b = select_parents(population, fitness)
  
  # Crossover
  population[:pop_size//2,:] = crossover(parents_a)
  population[pop_size//2:,:] = crossover(parents_b)
  
  # Mutation
  for i in range(pop_size):
    if np.random.rand() < mutation_prob:
      population[i,:] = mutate(population[i,:])
 
# Plot the final result (Optional)
x_vals = np.linspace(-1*np.pi, np.pi, 50)
y_vals = np.linspace(-1*np.pi, np.pi, 50)
z_vals = np.zeros((len(x_vals), len(y_vals)))
for i in range(len(x_vals)):
    for j in range(len(y_vals)):
        z_vals[i,j] = f(x_vals[i], y_vals[j])

X, Y = np.meshgrid(x_vals, y_vals)
fig = plt.figure(figsize=(6,5))
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(X, Y, z_vals, cmap='viridis')
ax.scatter(x, y, fitness[index], s=100, color='red')
plt.title(f'Result: f({round(x,4)}, {round(y,4)}) = {round(fitness[index],4)}')
plt.show()
3317 chars
102 lines

This code utilizes the numpy library to handle numpy array operations efficiently and the matplotlib library to visualize the results. By running this code we can find maximum value of the function by optimizing the parameters x and y.

gistlibby LogSnag