Skip to main content
Code Review

Return to Question

added 23 characters in body; edited tags; edited title
Source Link
Jamal
  • 35.2k
  • 13
  • 134
  • 238

An efficient way of tackeling Tackling the TSP with a genetic algorithm in python?

MyThis is my first go at genetic algorithms, used pygameusing PyGame for the visual representation. Is there a way to improve the speed of the code? Click to place a point, press arrow key up to start looking for the shortest route, or press cc to clear all.

An efficient way of tackeling the TSP with a genetic algorithm in python?

My first go at genetic algorithms, used pygame for the visual representation. Is there a way to improve the speed of the code? Click to place a point, press arrow key up to start looking for the shortest route, press c to clear all.

Tackling the TSP with a genetic algorithm

This is my first go at genetic algorithms, using PyGame for the visual representation. Is there a way to improve the speed of the code? Click to place a point, press to start looking for the shortest route, or press c to clear all.

improves formatting
Source Link
palacsint
  • 30.3k
  • 9
  • 82
  • 157

An efficiëntefficient way of tackeling the TSP with a genetic algorithm in python?

My first go at genetic algorithms, used pygame for the visual representation. Is there a way to improve the speed of the code? clickClick to place a point, press arrow key up to start looking for the shortest route, press c to clear all.

import pygame, time, random
#Size of next generation, change number at the end if needed
resize_rate = 1.005
#Controls crossover appearence
cross_rate = 0.7
#Controls number of chromosomes created at the start, exponential
exponent = 4
black = (0, 0, 0)
white = (255, 255, 255)
red = (255, 0, 0)
genes = []
def draw_background(screen):
 screen.fill(white)
def draw_connection(screen, pointlist):
 pygame.draw.lines(screen, black, True, pointlist, 1)
def draw_best_connection(screen, pointlist):
 pygame.draw.lines(screen, red, True, pointlist, 2)
def create_random_chromosomes(genes):
 temp_chromosomes = []
 chromosomes = []
 for i in range(len(genes)**exponent):
 genes_copy = genes[:]
 random.shuffle(genes_copy)
 temp_chromosomes.append(genes_copy)
 for element in temp_chromosomes:
 if element not in chromosomes:
 chromosomes.append(element)
 print(str(len(chromosomes)) + " random chromosomes created")
 return chromosomes
def calculate_distance(chromosome):
 distances = []
 total_distance = 0
 for i in range(len(chromosome)):
 if i < (len(chromosome)-1):
 distance_A_B = (((chromosome[i+1][0]-chromosome[i][0])**2)+(chromosome[i+1][1]-chromosome[i][1])**2)**0.5
 distances.append(distance_A_B)
 else:
 distance_A_B = (((chromosome[i][0]-chromosome[0][0])**2)+(chromosome[i][1]-chromosome[0][1])**2)**0.5
 distances.append(distance_A_B)
 for i in range(len(distances)):
 total_distance += distances[i]
 return total_distance
def calculate_fitness(chromosomes):
 fitness_scores = []
 for i in range(len(chromosomes)):
 fitness = 0
 fitness = 1/calculate_distance(chromosomes[i])
 fitness_scores.append(fitness)
 return fitness_scores
def build_chromosome_fitness_dict(chromosomes, fitness_scores):
 chrom_fit_dict = {}
 for i in range(len(chromosomes)):
 chrom_fit_dict[fitness_scores[i]] = chromosomes[i]
 return chrom_fit_dict
def roulette_selection(chromosomes, fitnesses, new_size):
 sum_fitness = sum(fitnesses)
 rel_fitness = [fitness/sum_fitness for fitness in fitnesses]
 #Generate probability intervals for each chromosome
 probabilities = [sum(rel_fitness[:i+1]) for i in range(len(rel_fitness))]
 #Select chromosomes
 selected_chromosomes = []
 for n in range(new_size):
 r = random.random()
 for (i, chromosome) in enumerate(chromosomes):
 if r <= probabilities[i]:
 selected_chromosomes.append(chromosome)
 break
 return selected_chromosomes
def find_closest(cities):
 dist_a = (((cities[0][0]-cities[1][0])**2)+(cities[0][1]-cities[1][1])**2)**0.5
 dist_b = (((cities[0][0]-cities[2][0])**2)+(cities[0][1]-cities[2][1])**2)**0.5
 if dist_a < dist_b:
 return cities[1]
 else:
 return cities[2]
#Greedy crossover selects the first city of one parent,
#compares the cities leaving that city in both parents,
#and chooses the closer one to extend the tour.
#If one city has already appeared in the tour, we choose the other city.
#If both cities have already appeared, we randomly select a non-selected city. 
def crossover(chromosomes, rate):
 new_chromosomes = []
 #len -1 because index out of range error might occur otherwise
 for i in range(len(chromosomes)-1):
 #Crossover T/F
 if random.random() < rate:
 #Take 2 chromosomes
 a = chromosomes[i]
 b = chromosomes[i+1]
 #Randomly select crossover location
 cross_location = random.randint(1, len(chromosomes[i]))
 #Create parts
 c = a[:cross_location]
 for i in range((len(a)-len(c))):
 #City to start from
 start_pos = c[-1]
 #2 most plausible targets
 target_0 = a[cross_location+i]
 target_1 = b[cross_location+i]
 #Determine if targets already appear in c and add correct city
 if target_0 in c:
 if target_1 in c:
 not_yet_selected = []
 for city in genes:
 if city not in c:
 not_yet_selected.append(city)
 c.append(not_yet_selected[random.randint(0,(len(not_yet_selected)-1))])
 else:
 c.append(target_1)
 elif target_1 in c:
 c.append(target_0)
 else:
 citiesc.append(target_1)
 = [start_pos, target_0, target_1]
 elif target_1 in c:
 closest = find_closest c.append(citiestarget_0)
 else:
 c.append( cities = [start_pos, target_0, target_1]
 closest = find_closest(cities)
 new_chromosomes c.append(cclosest)
 else:new_chromosomes.append(c)
 else:
  new_chromosomes.append(chromosomes[i])
 return new_chromosomes
pygame.init()
screen = pygame.display.set_mode((640,340))
clock = pygame.time.Clock()
done = False
first = True
while done == False:
 for event in pygame.event.get():
 if event.type == pygame.QUIT:
 done = True
 if event.type == pygame.KEYDOWN:
 if event.key == pygame.K_UP:
 if genes != []:
 #Start Genetic Algorithm
 print('Creating initial solutions')
 chromosomes = create_random_chromosomes(genes)
 #Draw most possible solutions
 for i in range(len(chromosomes)):
 draw_connection(screen, chromosomes[i])
 #Main Logic Loop
 print('Starting calculations')
 while len(chromosomes) > 10:
 print(str(len(chromosomes)) + ' chromosomes left')
 new_size = int(len(chromosomes)/resize_rate)
 #Calculate fitness scores
 fitness_scores = calculate_fitness(chromosomes)
 #Build dictionary to preserve order
 chrom_fit_dict = build_chromosome_fitness_dict(chromosomes, fitness_scores)
 #Roulette selection - select chromosomes for next generation
 selected_chromosomes = roulette_selection(chromosomes, fitness_scores, new_size)
 #Adopt newly selected chromosomes as population
 chromosomes = selected_chromosomes
 #Apply crossover mutation
 mutated_chromosomes = crossover(chromosomes, cross_rate)
 #Adopt mutated chromosomes as population
 chromosomes = mutated_chromosomes
 best_chrom = fitness_scores.index(max(chrom_fit_dict))
 draw_best_connection(screen, chromosomes[best_chrom])
 if event.key == pygame.K_c:
 draw_background(screen)
 genes = []
 if first == True:
 draw_background(screen)
 first = False
 #Get points
 if pygame.mouse.get_pressed() == (1, 0, 0):
 mouse_pos = pygame.mouse.get_pos()
 genes.append(mouse_pos)
 pygame.draw.rect(screen, black, [mouse_pos[0], mouse_pos[1], 2, 2], 1)
 genes = list(set(genes))
 pygame.display.flip()
 clock.tick(30)
pygame.quit()

An efficiënt way of tackeling the TSP with a genetic algorithm in python?

My first go at genetic algorithms, used pygame for the visual representation. Is there a way to improve the speed of the code? click to place a point, press arrow key up to start looking for the shortest route, press c to clear all.

import pygame, time, random
#Size of next generation, change number at the end if needed
resize_rate = 1.005
#Controls crossover appearence
cross_rate = 0.7
#Controls number of chromosomes created at the start, exponential
exponent = 4
black = (0, 0, 0)
white = (255, 255, 255)
red = (255, 0, 0)
genes = []
def draw_background(screen):
 screen.fill(white)
def draw_connection(screen, pointlist):
 pygame.draw.lines(screen, black, True, pointlist, 1)
def draw_best_connection(screen, pointlist):
 pygame.draw.lines(screen, red, True, pointlist, 2)
def create_random_chromosomes(genes):
 temp_chromosomes = []
 chromosomes = []
 for i in range(len(genes)**exponent):
 genes_copy = genes[:]
 random.shuffle(genes_copy)
 temp_chromosomes.append(genes_copy)
 for element in temp_chromosomes:
 if element not in chromosomes:
 chromosomes.append(element)
 print(str(len(chromosomes)) + " random chromosomes created")
 return chromosomes
def calculate_distance(chromosome):
 distances = []
 total_distance = 0
 for i in range(len(chromosome)):
 if i < (len(chromosome)-1):
 distance_A_B = (((chromosome[i+1][0]-chromosome[i][0])**2)+(chromosome[i+1][1]-chromosome[i][1])**2)**0.5
 distances.append(distance_A_B)
 else:
 distance_A_B = (((chromosome[i][0]-chromosome[0][0])**2)+(chromosome[i][1]-chromosome[0][1])**2)**0.5
 distances.append(distance_A_B)
 for i in range(len(distances)):
 total_distance += distances[i]
 return total_distance
def calculate_fitness(chromosomes):
 fitness_scores = []
 for i in range(len(chromosomes)):
 fitness = 0
 fitness = 1/calculate_distance(chromosomes[i])
 fitness_scores.append(fitness)
 return fitness_scores
def build_chromosome_fitness_dict(chromosomes, fitness_scores):
 chrom_fit_dict = {}
 for i in range(len(chromosomes)):
 chrom_fit_dict[fitness_scores[i]] = chromosomes[i]
 return chrom_fit_dict
def roulette_selection(chromosomes, fitnesses, new_size):
 sum_fitness = sum(fitnesses)
 rel_fitness = [fitness/sum_fitness for fitness in fitnesses]
 #Generate probability intervals for each chromosome
 probabilities = [sum(rel_fitness[:i+1]) for i in range(len(rel_fitness))]
 #Select chromosomes
 selected_chromosomes = []
 for n in range(new_size):
 r = random.random()
 for (i, chromosome) in enumerate(chromosomes):
 if r <= probabilities[i]:
 selected_chromosomes.append(chromosome)
 break
 return selected_chromosomes
def find_closest(cities):
 dist_a = (((cities[0][0]-cities[1][0])**2)+(cities[0][1]-cities[1][1])**2)**0.5
 dist_b = (((cities[0][0]-cities[2][0])**2)+(cities[0][1]-cities[2][1])**2)**0.5
 if dist_a < dist_b:
 return cities[1]
 else:
 return cities[2]
#Greedy crossover selects the first city of one parent,
#compares the cities leaving that city in both parents,
#and chooses the closer one to extend the tour.
#If one city has already appeared in the tour, we choose the other city.
#If both cities have already appeared, we randomly select a non-selected city. 
def crossover(chromosomes, rate):
 new_chromosomes = []
 #len -1 because index out of range error might occur otherwise
 for i in range(len(chromosomes)-1):
 #Crossover T/F
 if random.random() < rate:
 #Take 2 chromosomes
 a = chromosomes[i]
 b = chromosomes[i+1]
 #Randomly select crossover location
 cross_location = random.randint(1, len(chromosomes[i]))
 #Create parts
 c = a[:cross_location]
 for i in range((len(a)-len(c))):
 #City to start from
 start_pos = c[-1]
 #2 most plausible targets
 target_0 = a[cross_location+i]
 target_1 = b[cross_location+i]
 #Determine if targets already appear in c and add correct city
 if target_0 in c:
 if target_1 in c:
 not_yet_selected = []
 for city in genes:
 if city not in c:
 not_yet_selected.append(city)
 c.append(not_yet_selected[random.randint(0,(len(not_yet_selected)-1))])
 else:
 c.append(target_1)
 elif target_1 in c:
 c.append(target_0)
 else:
 cities = [start_pos, target_0, target_1]
 closest = find_closest(cities)
 c.append(closest)
 new_chromosomes.append(c)
 else:
 new_chromosomes.append(chromosomes[i])
 return new_chromosomes
pygame.init()
screen = pygame.display.set_mode((640,340))
clock = pygame.time.Clock()
done = False
first = True
while done == False:
 for event in pygame.event.get():
 if event.type == pygame.QUIT:
 done = True
 if event.type == pygame.KEYDOWN:
 if event.key == pygame.K_UP:
 if genes != []:
 #Start Genetic Algorithm
 print('Creating initial solutions')
 chromosomes = create_random_chromosomes(genes)
 #Draw most possible solutions
 for i in range(len(chromosomes)):
 draw_connection(screen, chromosomes[i])
 #Main Logic Loop
 print('Starting calculations')
 while len(chromosomes) > 10:
 print(str(len(chromosomes)) + ' chromosomes left')
 new_size = int(len(chromosomes)/resize_rate)
 #Calculate fitness scores
 fitness_scores = calculate_fitness(chromosomes)
 #Build dictionary to preserve order
 chrom_fit_dict = build_chromosome_fitness_dict(chromosomes, fitness_scores)
 #Roulette selection - select chromosomes for next generation
 selected_chromosomes = roulette_selection(chromosomes, fitness_scores, new_size)
 #Adopt newly selected chromosomes as population
 chromosomes = selected_chromosomes
 #Apply crossover mutation
 mutated_chromosomes = crossover(chromosomes, cross_rate)
 #Adopt mutated chromosomes as population
 chromosomes = mutated_chromosomes
 best_chrom = fitness_scores.index(max(chrom_fit_dict))
 draw_best_connection(screen, chromosomes[best_chrom])
 if event.key == pygame.K_c:
 draw_background(screen)
 genes = []
 if first == True:
 draw_background(screen)
 first = False
 #Get points
 if pygame.mouse.get_pressed() == (1, 0, 0):
 mouse_pos = pygame.mouse.get_pos()
 genes.append(mouse_pos)
 pygame.draw.rect(screen, black, [mouse_pos[0], mouse_pos[1], 2, 2], 1)
 genes = list(set(genes))
 pygame.display.flip()
 clock.tick(30)
pygame.quit()

An efficient way of tackeling the TSP with a genetic algorithm in python?

My first go at genetic algorithms, used pygame for the visual representation. Is there a way to improve the speed of the code? Click to place a point, press arrow key up to start looking for the shortest route, press c to clear all.

import pygame, time, random
#Size of next generation, change number at the end if needed
resize_rate = 1.005
#Controls crossover appearence
cross_rate = 0.7
#Controls number of chromosomes created at the start, exponential
exponent = 4
black = (0, 0, 0)
white = (255, 255, 255)
red = (255, 0, 0)
genes = []
def draw_background(screen):
 screen.fill(white)
def draw_connection(screen, pointlist):
 pygame.draw.lines(screen, black, True, pointlist, 1)
def draw_best_connection(screen, pointlist):
 pygame.draw.lines(screen, red, True, pointlist, 2)
def create_random_chromosomes(genes):
 temp_chromosomes = []
 chromosomes = []
 for i in range(len(genes)**exponent):
 genes_copy = genes[:]
 random.shuffle(genes_copy)
 temp_chromosomes.append(genes_copy)
 for element in temp_chromosomes:
 if element not in chromosomes:
 chromosomes.append(element)
 print(str(len(chromosomes)) + " random chromosomes created")
 return chromosomes
def calculate_distance(chromosome):
 distances = []
 total_distance = 0
 for i in range(len(chromosome)):
 if i < (len(chromosome)-1):
 distance_A_B = (((chromosome[i+1][0]-chromosome[i][0])**2)+(chromosome[i+1][1]-chromosome[i][1])**2)**0.5
 distances.append(distance_A_B)
 else:
 distance_A_B = (((chromosome[i][0]-chromosome[0][0])**2)+(chromosome[i][1]-chromosome[0][1])**2)**0.5
 distances.append(distance_A_B)
 for i in range(len(distances)):
 total_distance += distances[i]
 return total_distance
def calculate_fitness(chromosomes):
 fitness_scores = []
 for i in range(len(chromosomes)):
 fitness = 0
 fitness = 1/calculate_distance(chromosomes[i])
 fitness_scores.append(fitness)
 return fitness_scores
def build_chromosome_fitness_dict(chromosomes, fitness_scores):
 chrom_fit_dict = {}
 for i in range(len(chromosomes)):
 chrom_fit_dict[fitness_scores[i]] = chromosomes[i]
 return chrom_fit_dict
def roulette_selection(chromosomes, fitnesses, new_size):
 sum_fitness = sum(fitnesses)
 rel_fitness = [fitness/sum_fitness for fitness in fitnesses]
 #Generate probability intervals for each chromosome
 probabilities = [sum(rel_fitness[:i+1]) for i in range(len(rel_fitness))]
 #Select chromosomes
 selected_chromosomes = []
 for n in range(new_size):
 r = random.random()
 for (i, chromosome) in enumerate(chromosomes):
 if r <= probabilities[i]:
 selected_chromosomes.append(chromosome)
 break
 return selected_chromosomes
def find_closest(cities):
 dist_a = (((cities[0][0]-cities[1][0])**2)+(cities[0][1]-cities[1][1])**2)**0.5
 dist_b = (((cities[0][0]-cities[2][0])**2)+(cities[0][1]-cities[2][1])**2)**0.5
 if dist_a < dist_b:
 return cities[1]
 else:
 return cities[2]
#Greedy crossover selects the first city of one parent,
#compares the cities leaving that city in both parents,
#and chooses the closer one to extend the tour.
#If one city has already appeared in the tour, we choose the other city.
#If both cities have already appeared, we randomly select a non-selected city. 
def crossover(chromosomes, rate):
 new_chromosomes = []
 #len -1 because index out of range error might occur otherwise
 for i in range(len(chromosomes)-1):
 #Crossover T/F
 if random.random() < rate:
 #Take 2 chromosomes
 a = chromosomes[i]
 b = chromosomes[i+1]
 #Randomly select crossover location
 cross_location = random.randint(1, len(chromosomes[i]))
 #Create parts
 c = a[:cross_location]
 for i in range((len(a)-len(c))):
 #City to start from
 start_pos = c[-1]
 #2 most plausible targets
 target_0 = a[cross_location+i]
 target_1 = b[cross_location+i]
 #Determine if targets already appear in c and add correct city
 if target_0 in c:
 if target_1 in c:
 not_yet_selected = []
 for city in genes:
 if city not in c:
 not_yet_selected.append(city)
 c.append(not_yet_selected[random.randint(0,(len(not_yet_selected)-1))])
 else:
 c.append(target_1)
 elif target_1 in c:
  c.append(target_0)
 else:
  cities = [start_pos, target_0, target_1]
 closest = find_closest(cities)
  c.append(closest)
 new_chromosomes.append(c)
 else:
  new_chromosomes.append(chromosomes[i])
 return new_chromosomes
pygame.init()
screen = pygame.display.set_mode((640,340))
clock = pygame.time.Clock()
done = False
first = True
while done == False:
 for event in pygame.event.get():
 if event.type == pygame.QUIT:
 done = True
 if event.type == pygame.KEYDOWN:
 if event.key == pygame.K_UP:
 if genes != []:
 #Start Genetic Algorithm
 print('Creating initial solutions')
 chromosomes = create_random_chromosomes(genes)
 #Draw most possible solutions
 for i in range(len(chromosomes)):
 draw_connection(screen, chromosomes[i])
 #Main Logic Loop
 print('Starting calculations')
 while len(chromosomes) > 10:
 print(str(len(chromosomes)) + ' chromosomes left')
 new_size = int(len(chromosomes)/resize_rate)
 #Calculate fitness scores
 fitness_scores = calculate_fitness(chromosomes)
 #Build dictionary to preserve order
 chrom_fit_dict = build_chromosome_fitness_dict(chromosomes, fitness_scores)
 #Roulette selection - select chromosomes for next generation
 selected_chromosomes = roulette_selection(chromosomes, fitness_scores, new_size)
 #Adopt newly selected chromosomes as population
 chromosomes = selected_chromosomes
 #Apply crossover mutation
 mutated_chromosomes = crossover(chromosomes, cross_rate)
 #Adopt mutated chromosomes as population
 chromosomes = mutated_chromosomes
 best_chrom = fitness_scores.index(max(chrom_fit_dict))
 draw_best_connection(screen, chromosomes[best_chrom])
 if event.key == pygame.K_c:
 draw_background(screen)
 genes = []
 if first == True:
 draw_background(screen)
 first = False
 #Get points
 if pygame.mouse.get_pressed() == (1, 0, 0):
 mouse_pos = pygame.mouse.get_pos()
 genes.append(mouse_pos)
 pygame.draw.rect(screen, black, [mouse_pos[0], mouse_pos[1], 2, 2], 1)
 genes = list(set(genes))
 pygame.display.flip()
 clock.tick(30)
pygame.quit()
fixed a problem with the resizing of the population
Source Link
Daquicker
  • 155
  • 1
  • 4
 import pygame, time, random
 #Size of next generation, change number at the end if needed
 resize_rate = 1.2005
 #Controls crossover appearence
 cross_rate = 0.7
 #Controls number of iterations
 iterations = 10000
 #Controls number of chromosomes created at the start, exponential
 exponent = 4
 black = (0, 0, 0)
 white = (255, 255, 255)
 red = (255, 0, 0)
 genes = []
 def draw_background(screen):
 screen.fill(white)
 def draw_connection(screen, pointlist):
 pygame.draw.lines(screen, black, True, pointlist, 1)
 def draw_best_connection(screen, pointlist):
 pygame.draw.lines(screen, red, True, pointlist, 2)
 def create_random_chromosomes(genes):
 temp_chromosomes = []
 chromosomes = []
 for i in range(len(genes)**exponent):
 genes_copy = genes[:]
 random.shuffle(genes_copy)
 temp_chromosomes.append(genes_copy)
 for element in temp_chromosomes:
 if element not in chromosomes:
 chromosomes.append(element)
 print(str(len(chromosomes)) + " random chromosomes created")
 return chromosomes
 def calculate_distance(chromosome):
 distances = []
 total_distance = 0
 for i in range(len(chromosome)):
 if i < (len(chromosome)-1):
 distance_A_B = (((chromosome[i+1][0]-chromosome[i][0])**2)+(chromosome[i+1][1]-chromosome[i][1])**2)**0.5
 distances.append(distance_A_B)
 else:
 distance_A_B = (((chromosome[i][0]-chromosome[0][0])**2)+(chromosome[i][1]-chromosome[0][1])**2)**0.5
 distances.append(distance_A_B)
 for i in range(len(distances)):
 total_distance += distances[i]
 return total_distance
 def calculate_fitness(chromosomes):
 fitness_scores = []
 for i in range(len(chromosomes)):
 fitness = 0
 fitness = 1/calculate_distance(chromosomes[i])
 fitness_scores.append(fitness)
 return fitness_scores
 def build_chromosome_fitness_dict(chromosomes, fitness_scores):
 chrom_fit_dict = {}
 for i in range(len(chromosomes)):
 chrom_fit_dict[fitness_scores[i]] = chromosomes[i]
 return chrom_fit_dict
 def roulette_selection(chromosomes, fitnesses, new_size):
 sum_fitness = sum(fitnesses)
 rel_fitness = [fitness/sum_fitness for fitness in fitnesses]
 #Generate probability intervals for each chromosome
 probabilities = [sum(rel_fitness[:i+1]) for i in range(len(rel_fitness))]
 #Select chromosomes
 selected_chromosomes = []
 for n in range(new_size):
 r = random.random()
 for (i, chromosome) in enumerate(chromosomes):
 if r <= probabilities[i]:
 selected_chromosomes.append(chromosome)
 break
 return selected_chromosomes
 def find_closest(cities):
 dist_a = (((cities[0][0]-cities[1][0])**2)+(cities[0][1]-cities[1][1])**2)**0.5
 dist_b = (((cities[0][0]-cities[2][0])**2)+(cities[0][1]-cities[2][1])**2)**0.5
 if dist_a < dist_b:
 return cities[1]
 else:
 return cities[2]
 #Greedy crossover selects the first city of one parent,
 #compares the cities leaving that city in both parents,
 #and chooses the closer one to extend the tour.
 #If one city has already appeared in the tour, we choose the other city.
 #If both cities have already appeared, we randomly select a non-selected city. 
 def crossover(chromosomes, rate):
 new_chromosomes = []
 #len -1 because index out of range error might occur otherwise
 for i in range(len(chromosomes)-1):
 #Crossover T/F
 if random.random() < rate:
 #Take 2 chromosomes
 a = chromosomes[i]
 b = chromosomes[i+1]
 #Randomly select crossover location
 cross_location = random.randint(1, len(chromosomes[i]))
 #Create parts
 c = a[:cross_location]
 for i in range((len(a)-len(c))):
 #City to start from
 start_pos = c[-1]
 #2 most plausible targets
 target_0 = a[cross_location+i]
 target_1 = b[cross_location+i]
 #Determine if targets already appear in c and add correct city
 if target_0 in c:
 if target_1 in c:
 not_yet_selected = []
 for city in genes:
 if city not in c:
 not_yet_selected.append(city)
 c.append(not_yet_selected[random.randint(0,(len(not_yet_selected)-1))])
 else:
 c.append(target_1)
 elif target_1 in c:
 c.append(target_0)
 else:
 cities = [start_pos, target_0, target_1]
 closest = find_closest(cities)
 c.append(closest)
 new_chromosomes.append(c)
 else:
 new_chromosomes.append(chromosomes[i])
 return new_chromosomes
 pygame.init()
 screen = pygame.display.set_mode((640,340))
 clock = pygame.time.Clock()
 done = False
 first = True
 while done == False:
 for event in pygame.event.get():
 if event.type == pygame.QUIT:
 done = True
 if event.type == pygame.KEYDOWN:
 if event.key == pygame.K_UP:
 if genes != []:
 #Start Genetic Algorithm
 print('Creating initial solutions')
 chromosomes = create_random_chromosomes(genes)
 print('Initial solutions created')
 #Draw most possible solutions
 for i in range(len(chromosomes)):
 draw_connection(screen, chromosomes[i])
 new_size = int(len(chromosomes)/resize_rate)
 #Main Logic Loop
 print('Starting calculations')
 for i inwhile rangelen(iterationschromosomes):
  > 10:
 if i % print(iterations/100str(len(chromosomes)) ==+ 0:
' chromosomes left')
 new_size = print(strint(i/len(iterations/100)chromosomes) + "% complete"/resize_rate)
 #Calculate fitness scores
 fitness_scores = calculate_fitness(chromosomes)
 #Build dictionary to preserve order
 chrom_fit_dict = build_chromosome_fitness_dict(chromosomes, fitness_scores)
 #Roulette selection - select chromosomes for next generation
 selected_chromosomes = roulette_selection(chromosomes, fitness_scores, new_size)
 #Adopt newly selected chromosomes as population
 chromosomes = selected_chromosomes
 #Apply crossover mutation
 mutated_chromosomes = crossover(chromosomes, cross_rate)
 #Adopt mutated chromosomes as population
 chromosomes = mutated_chromosomes
 best_chrom = fitness_scores.index(max(chrom_fit_dict))
 draw_best_connection(screen, chromosomes[best_chrom])
 if event.key == pygame.K_c:
 draw_background(screen)
 genes = []
 if first == True:
 draw_background(screen)
 first = False
 #Get points
 if pygame.mouse.get_pressed() == (1, 0, 0):
 mouse_pos = pygame.mouse.get_pos()
 genes.append(mouse_pos)
 pygame.draw.rect(screen, black, [mouse_pos[0], mouse_pos[1], 2, 2], 1)
 genes = list(set(genes))
 pygame.display.flip()
 clock.tick(30)
 pygame.quit()
 import pygame, time, random
 #Size of next generation, change number at the end if needed
 resize_rate = 1.2
 #Controls crossover appearence
 cross_rate = 0.7
 #Controls number of iterations
 iterations = 10000
 #Controls number of chromosomes created at the start, exponential
 exponent = 4
 black = (0, 0, 0)
 white = (255, 255, 255)
 red = (255, 0, 0)
 genes = []
 def draw_background(screen):
 screen.fill(white)
 def draw_connection(screen, pointlist):
 pygame.draw.lines(screen, black, True, pointlist, 1)
 def draw_best_connection(screen, pointlist):
 pygame.draw.lines(screen, red, True, pointlist, 2)
 def create_random_chromosomes(genes):
 temp_chromosomes = []
 chromosomes = []
 for i in range(len(genes)**exponent):
 genes_copy = genes[:]
 random.shuffle(genes_copy)
 temp_chromosomes.append(genes_copy)
 for element in temp_chromosomes:
 if element not in chromosomes:
 chromosomes.append(element)
 print(str(len(chromosomes)) + " random chromosomes created")
 return chromosomes
 def calculate_distance(chromosome):
 distances = []
 total_distance = 0
 for i in range(len(chromosome)):
 if i < (len(chromosome)-1):
 distance_A_B = (((chromosome[i+1][0]-chromosome[i][0])**2)+(chromosome[i+1][1]-chromosome[i][1])**2)**0.5
 distances.append(distance_A_B)
 else:
 distance_A_B = (((chromosome[i][0]-chromosome[0][0])**2)+(chromosome[i][1]-chromosome[0][1])**2)**0.5
 distances.append(distance_A_B)
 for i in range(len(distances)):
 total_distance += distances[i]
 return total_distance
 def calculate_fitness(chromosomes):
 fitness_scores = []
 for i in range(len(chromosomes)):
 fitness = 0
 fitness = 1/calculate_distance(chromosomes[i])
 fitness_scores.append(fitness)
 return fitness_scores
 def build_chromosome_fitness_dict(chromosomes, fitness_scores):
 chrom_fit_dict = {}
 for i in range(len(chromosomes)):
 chrom_fit_dict[fitness_scores[i]] = chromosomes[i]
 return chrom_fit_dict
 def roulette_selection(chromosomes, fitnesses, new_size):
 sum_fitness = sum(fitnesses)
 rel_fitness = [fitness/sum_fitness for fitness in fitnesses]
 #Generate probability intervals for each chromosome
 probabilities = [sum(rel_fitness[:i+1]) for i in range(len(rel_fitness))]
 #Select chromosomes
 selected_chromosomes = []
 for n in range(new_size):
 r = random.random()
 for (i, chromosome) in enumerate(chromosomes):
 if r <= probabilities[i]:
 selected_chromosomes.append(chromosome)
 break
 return selected_chromosomes
 def find_closest(cities):
 dist_a = (((cities[0][0]-cities[1][0])**2)+(cities[0][1]-cities[1][1])**2)**0.5
 dist_b = (((cities[0][0]-cities[2][0])**2)+(cities[0][1]-cities[2][1])**2)**0.5
 if dist_a < dist_b:
 return cities[1]
 else:
 return cities[2]
 #Greedy crossover selects the first city of one parent,
 #compares the cities leaving that city in both parents,
 #and chooses the closer one to extend the tour.
 #If one city has already appeared in the tour, we choose the other city.
 #If both cities have already appeared, we randomly select a non-selected city. 
 def crossover(chromosomes, rate):
 new_chromosomes = []
 #len -1 because index out of range error might occur otherwise
 for i in range(len(chromosomes)-1):
 #Crossover T/F
 if random.random() < rate:
 #Take 2 chromosomes
 a = chromosomes[i]
 b = chromosomes[i+1]
 #Randomly select crossover location
 cross_location = random.randint(1, len(chromosomes[i]))
 #Create parts
 c = a[:cross_location]
 for i in range((len(a)-len(c))):
 #City to start from
 start_pos = c[-1]
 #2 most plausible targets
 target_0 = a[cross_location+i]
 target_1 = b[cross_location+i]
 #Determine if targets already appear in c and add correct city
 if target_0 in c:
 if target_1 in c:
 not_yet_selected = []
 for city in genes:
 if city not in c:
 not_yet_selected.append(city)
 c.append(not_yet_selected[random.randint(0,(len(not_yet_selected)-1))])
 else:
 c.append(target_1)
 elif target_1 in c:
 c.append(target_0)
 else:
 cities = [start_pos, target_0, target_1]
 closest = find_closest(cities)
 c.append(closest)
 new_chromosomes.append(c)
 return new_chromosomes
 pygame.init()
 screen = pygame.display.set_mode((640,340))
 clock = pygame.time.Clock()
 done = False
 first = True
 while done == False:
 for event in pygame.event.get():
 if event.type == pygame.QUIT:
 done = True
 if event.type == pygame.KEYDOWN:
 if event.key == pygame.K_UP:
 if genes != []:
 #Start Genetic Algorithm
 print('Creating initial solutions')
 chromosomes = create_random_chromosomes(genes)
 print('Initial solutions created')
 #Draw most possible solutions
 for i in range(len(chromosomes)):
 draw_connection(screen, chromosomes[i])
 new_size = int(len(chromosomes)/resize_rate)
 #Main Logic Loop
 print('Starting calculations')
 for i in range(iterations):
  if i % (iterations/100) == 0:
 print(str(i/(iterations/100)) + "% complete")
 #Calculate fitness scores
 fitness_scores = calculate_fitness(chromosomes)
 #Build dictionary to preserve order
 chrom_fit_dict = build_chromosome_fitness_dict(chromosomes, fitness_scores)
 #Roulette selection - select chromosomes for next generation
 selected_chromosomes = roulette_selection(chromosomes, fitness_scores, new_size)
 #Adopt newly selected chromosomes as population
 chromosomes = selected_chromosomes
 #Apply crossover mutation
 mutated_chromosomes = crossover(chromosomes, cross_rate)
 #Adopt mutated chromosomes as population
 chromosomes = mutated_chromosomes
 best_chrom = fitness_scores.index(max(chrom_fit_dict))
 draw_best_connection(screen, chromosomes[best_chrom])
 if event.key == pygame.K_c:
 draw_background(screen)
 genes = []
 if first == True:
 draw_background(screen)
 first = False
 #Get points
 if pygame.mouse.get_pressed() == (1, 0, 0):
 mouse_pos = pygame.mouse.get_pos()
 genes.append(mouse_pos)
 pygame.draw.rect(screen, black, [mouse_pos[0], mouse_pos[1], 2, 2], 1)
 genes = list(set(genes))
 pygame.display.flip()
 clock.tick(30)
 pygame.quit()
 import pygame, time, random
 #Size of next generation, change number at the end if needed
 resize_rate = 1.005
 #Controls crossover appearence
 cross_rate = 0.7
 #Controls number of chromosomes created at the start, exponential
 exponent = 4
 black = (0, 0, 0)
 white = (255, 255, 255)
 red = (255, 0, 0)
 genes = []
 def draw_background(screen):
 screen.fill(white)
 def draw_connection(screen, pointlist):
 pygame.draw.lines(screen, black, True, pointlist, 1)
 def draw_best_connection(screen, pointlist):
 pygame.draw.lines(screen, red, True, pointlist, 2)
 def create_random_chromosomes(genes):
 temp_chromosomes = []
 chromosomes = []
 for i in range(len(genes)**exponent):
 genes_copy = genes[:]
 random.shuffle(genes_copy)
 temp_chromosomes.append(genes_copy)
 for element in temp_chromosomes:
 if element not in chromosomes:
 chromosomes.append(element)
 print(str(len(chromosomes)) + " random chromosomes created")
 return chromosomes
 def calculate_distance(chromosome):
 distances = []
 total_distance = 0
 for i in range(len(chromosome)):
 if i < (len(chromosome)-1):
 distance_A_B = (((chromosome[i+1][0]-chromosome[i][0])**2)+(chromosome[i+1][1]-chromosome[i][1])**2)**0.5
 distances.append(distance_A_B)
 else:
 distance_A_B = (((chromosome[i][0]-chromosome[0][0])**2)+(chromosome[i][1]-chromosome[0][1])**2)**0.5
 distances.append(distance_A_B)
 for i in range(len(distances)):
 total_distance += distances[i]
 return total_distance
 def calculate_fitness(chromosomes):
 fitness_scores = []
 for i in range(len(chromosomes)):
 fitness = 0
 fitness = 1/calculate_distance(chromosomes[i])
 fitness_scores.append(fitness)
 return fitness_scores
 def build_chromosome_fitness_dict(chromosomes, fitness_scores):
 chrom_fit_dict = {}
 for i in range(len(chromosomes)):
 chrom_fit_dict[fitness_scores[i]] = chromosomes[i]
 return chrom_fit_dict
 def roulette_selection(chromosomes, fitnesses, new_size):
 sum_fitness = sum(fitnesses)
 rel_fitness = [fitness/sum_fitness for fitness in fitnesses]
 #Generate probability intervals for each chromosome
 probabilities = [sum(rel_fitness[:i+1]) for i in range(len(rel_fitness))]
 #Select chromosomes
 selected_chromosomes = []
 for n in range(new_size):
 r = random.random()
 for (i, chromosome) in enumerate(chromosomes):
 if r <= probabilities[i]:
 selected_chromosomes.append(chromosome)
 break
 return selected_chromosomes
 def find_closest(cities):
 dist_a = (((cities[0][0]-cities[1][0])**2)+(cities[0][1]-cities[1][1])**2)**0.5
 dist_b = (((cities[0][0]-cities[2][0])**2)+(cities[0][1]-cities[2][1])**2)**0.5
 if dist_a < dist_b:
 return cities[1]
 else:
 return cities[2]
 #Greedy crossover selects the first city of one parent,
 #compares the cities leaving that city in both parents,
 #and chooses the closer one to extend the tour.
 #If one city has already appeared in the tour, we choose the other city.
 #If both cities have already appeared, we randomly select a non-selected city. 
 def crossover(chromosomes, rate):
 new_chromosomes = []
 #len -1 because index out of range error might occur otherwise
 for i in range(len(chromosomes)-1):
 #Crossover T/F
 if random.random() < rate:
 #Take 2 chromosomes
 a = chromosomes[i]
 b = chromosomes[i+1]
 #Randomly select crossover location
 cross_location = random.randint(1, len(chromosomes[i]))
 #Create parts
 c = a[:cross_location]
 for i in range((len(a)-len(c))):
 #City to start from
 start_pos = c[-1]
 #2 most plausible targets
 target_0 = a[cross_location+i]
 target_1 = b[cross_location+i]
 #Determine if targets already appear in c and add correct city
 if target_0 in c:
 if target_1 in c:
 not_yet_selected = []
 for city in genes:
 if city not in c:
 not_yet_selected.append(city)
 c.append(not_yet_selected[random.randint(0,(len(not_yet_selected)-1))])
 else:
 c.append(target_1)
 elif target_1 in c:
 c.append(target_0)
 else:
 cities = [start_pos, target_0, target_1]
 closest = find_closest(cities)
 c.append(closest)
 new_chromosomes.append(c)
 else:
 new_chromosomes.append(chromosomes[i])
 return new_chromosomes
 pygame.init()
 screen = pygame.display.set_mode((640,340))
 clock = pygame.time.Clock()
 done = False
 first = True
 while done == False:
 for event in pygame.event.get():
 if event.type == pygame.QUIT:
 done = True
 if event.type == pygame.KEYDOWN:
 if event.key == pygame.K_UP:
 if genes != []:
 #Start Genetic Algorithm
 print('Creating initial solutions')
 chromosomes = create_random_chromosomes(genes)
 #Draw most possible solutions
 for i in range(len(chromosomes)):
 draw_connection(screen, chromosomes[i])
 #Main Logic Loop
 print('Starting calculations')
 while len(chromosomes) > 10:
 print(str(len(chromosomes)) + ' chromosomes left')
 new_size = int(len(chromosomes)/resize_rate)
 #Calculate fitness scores
 fitness_scores = calculate_fitness(chromosomes)
 #Build dictionary to preserve order
 chrom_fit_dict = build_chromosome_fitness_dict(chromosomes, fitness_scores)
 #Roulette selection - select chromosomes for next generation
 selected_chromosomes = roulette_selection(chromosomes, fitness_scores, new_size)
 #Adopt newly selected chromosomes as population
 chromosomes = selected_chromosomes
 #Apply crossover mutation
 mutated_chromosomes = crossover(chromosomes, cross_rate)
 #Adopt mutated chromosomes as population
 chromosomes = mutated_chromosomes
 best_chrom = fitness_scores.index(max(chrom_fit_dict))
 draw_best_connection(screen, chromosomes[best_chrom])
 if event.key == pygame.K_c:
 draw_background(screen)
 genes = []
 if first == True:
 draw_background(screen)
 first = False
 #Get points
 if pygame.mouse.get_pressed() == (1, 0, 0):
 mouse_pos = pygame.mouse.get_pos()
 genes.append(mouse_pos)
 pygame.draw.rect(screen, black, [mouse_pos[0], mouse_pos[1], 2, 2], 1)
 genes = list(set(genes))
 pygame.display.flip()
 clock.tick(30)
 pygame.quit()
Source Link
Daquicker
  • 155
  • 1
  • 4
Loading
lang-py

AltStyle によって変換されたページ (->オリジナル) /