-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgeneticAlgorithmDistributed.py
More file actions
112 lines (80 loc) · 3.78 KB
/
geneticAlgorithmDistributed.py
File metadata and controls
112 lines (80 loc) · 3.78 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import time
import random
from geneticTasks import get_fitness_scores, mating, mutation
from utilityFunctions import Individual, City, Population, create_gene_pool, create_plot
class Generation(Population):
"""
Inherits parent class Population
Creates a population from a gene pool and specified size or from a gene pool and a list of individuals
Gets fitness scores and calculates the individuals with the best fitness scores
Can make the individuals with the best fitness scores mate and produce children individuals
"""
def __init__(self, gene_pool=None, size_of_population=10, individuals=None):
super().__init__(gene_pool, size_of_population, individuals)
def get_fitness_scores(self): # Distributed
"""
Return a dictionary of individuals and fitness scores
"""
individuals = []
fitness_scores = []
population = self.get_population()
results = ~get_fitness_scores.map(population)
for i in range(len(results)):
individuals.append(population[i])
fitness_scores.append(results[i])
return individuals, fitness_scores
def mate(self): # Distributed
"""
Gets the best individuals from the population
Takes a random subset of the second parents gene sequence and copies it directly into a copy of the
first parents gene sequence at the same positions. This is the new child gene sequence
Creates a new individual instance for every child
"""
best_individuals, extra_individuals = self.get_best_fitness_individuals()
# Mate the best individuals and receive a list of child gene sequences
children = ~mating.chunks([(best_individuals[i], best_individuals[i + 1]) for i in range(0, len(best_individuals), 2)], 10)
# Format the the list properly
children = children[0]
# Create a list of individuals from the list of child gene sequences
best_individuals += [Individual(gene_pool=self.gene_pool, gene_sequence=child_genes) for child_genes in children] + extra_individuals
return best_individuals
def mutate(self, mutation_rate):
if random.random() < mutation_rate:
population = self.get_population()
~mutation.map(population)
def average_fitnesses(individuals): # Distributed
"""
Calculate the average fitness score for a generation of individuals
"""
all_fitness_scores = ~get_fitness_scores.map(individuals)
return sum(all_fitness_scores) / len(individuals)
def main():
AMOUNT_OF_GENERATIONS = 100
SIZE_OF_POPULATION = 500
MUTATION_RATE = 0.2
start = time.monotonic()
# Create gene pool and initial population
gene_pool = create_gene_pool()
population = Generation(gene_pool=gene_pool, size_of_population=SIZE_OF_POPULATION)
generation = []
fitness_counts = []
generation_count = 0
while generation_count <= AMOUNT_OF_GENERATIONS:
generation.append(generation_count)
# Get all the individuals in the population
individuals = population.get_population()
# Calculate the average for the population in order to graph later
fitness_counts.append(average_fitnesses(individuals))
print('mating')
children = population.mate()
print('done')
# Create the new population as the children after mating the best half of the population and apply mutation
population = Generation(gene_pool=gene_pool, individuals=children)
population.mutate(MUTATION_RATE)
# Increment generation
generation_count += 1
print(time.monotonic() - start)
# Plot the average fitness score per generation
create_plot(generation, fitness_counts)
if __name__ == '__main__':
main()