-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgenetic_algorithm.py
More file actions
161 lines (117 loc) · 4.93 KB
/
Copy pathgenetic_algorithm.py
File metadata and controls
161 lines (117 loc) · 4.93 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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#from https://pythonhealthcare.org/2018/10/01/94-genetic-algorithms-a-simple-genetic-algorithm/
#Gentic algorithm simple example
import random
import numpy as np
def create_reference_solution(chromosome_length):
#pick randomly the number of ones in the chromosome
number_of_ones = int(chromosome_length / 2)
# Build an array with an equal mix of zero and ones
reference = np.zeros(chromosome_length)
reference[0: number_of_ones] = 1
# Shuffle the array to mix the zeros and ones
np.random.shuffle(reference)
return reference
def create_starting_population(individuals, chromosome_length):
# Set up an initial array of all zeros
population = np.zeros((individuals, chromosome_length))
# Loop through each row (individual)
for i in range(individuals):
# Choose a random number of ones to create
ones = random.randint(0, chromosome_length)
# Change the required number of zeros to ones
population[i, 0:ones] = 1
# Sfuffle row
np.random.shuffle(population[i])
return population
def calculate_fitness(reference, population):
# Create an array of True/False compared to reference
identical_to_reference = population == reference
# Sum number of genes that are identical to the reference
fitness_scores = identical_to_reference.sum(axis=1)
return fitness_scores
def select_individual_by_tournament(population, scores):
# Get population size
population_size = len(scores)
# Pick individuals for tournament
fighter_1 = random.randint(0, population_size - 1)
fighter_2 = random.randint(0, population_size - 1)
# Get fitness score for each
fighter_1_fitness = scores[fighter_1]
fighter_2_fitness = scores[fighter_2]
# Identify undividual with highest fitness
# Fighter 1 will win if score are equal
if fighter_1_fitness >= fighter_2_fitness:
winner = fighter_1
else:
winner = fighter_2
# Return the chromsome of the winner
return population[winner, :]
def breed_by_crossover(parent_1, parent_2):
# Get length of chromosome
chromosome_length = len(parent_1)
# Pick crossover point, avoding ends of chromsome
crossover_point = random.randint(1, chromosome_length - 1)
# Create children. np.hstack joins two arrays
child_1 = np.hstack((parent_1[0:crossover_point],
parent_2[crossover_point:]))
child_2 = np.hstack((parent_2[0:crossover_point],
parent_1[crossover_point:]))
# Return children
return child_1, child_2
def randomly_mutate_population(population, mutation_probability):
# Apply random mutation
random_mutation_array = np.random.random(
size=(population.shape))
random_mutation_boolean = \
random_mutation_array <= mutation_probability
population[random_mutation_boolean] = \
np.logical_not(population[random_mutation_boolean])
# Return mutation population
return population
# *************************************
# ******** MAIN ALGORITHM CODE ********
# *************************************
# Set general parameters
chromosome_length = 75
population_size = 500
maximum_generation = 200
best_score_progress = [] # Tracks progress
# Create reference solution
# (this is used just to illustrate GAs)
reference = create_reference_solution(chromosome_length)
# Create starting population of population size
population = create_starting_population(population_size, chromosome_length)
# Display best score in starting population
scores = calculate_fitness(reference, population)
best_score = np.max(scores) / chromosome_length * 100
print('Starting best score, % target: ', best_score)
# Add starting best score to progress tracker
best_score_progress.append(best_score)
# Now we'll go through the generations of genetic algorithm
for generation in range(maximum_generation):
# Create an empty list for new population
new_population = []
# Create new popualtion generating two children at a time
for i in range(int(population_size / 2)):
parent_1 = select_individual_by_tournament(population, scores)
parent_2 = select_individual_by_tournament(population, scores)
child_1, child_2 = breed_by_crossover(parent_1, parent_2)
new_population.append(child_1)
new_population.append(child_2)
# Replace the old population with the new one
population = np.array(new_population)
# Apply mutation
mutation_rate = 0.002
population = randomly_mutate_population(population, mutation_rate)
# Score best solution, and add to tracker
scores = calculate_fitness(reference, population)
best_score = np.max(scores) / chromosome_length * 100
best_score_progress.append(best_score)
# GA has completed required generation
print('End best score, % target: ', best_score)
# Plot progress
import matplotlib.pyplot as plt
plt.plot(best_score_progress)
plt.xlabel('Generation')
plt.ylabel('Best score (% target)')
plt.show()