-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathbasic_algorithm.py
More file actions
196 lines (154 loc) · 7.37 KB
/
basic_algorithm.py
File metadata and controls
196 lines (154 loc) · 7.37 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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
# imports framework
import sys
sys.path.insert(0, 'evoman')
from environment import Environment
from player_controller import player_controller
# imports other libs
import time
import numpy as np
from math import fabs,sqrt
import glob, os
import matplotlib.pyplot as plt
import pandas as pd
# import evolutionary algorithm functions
from parent_selection_methods import *
from mutation_recombination_methods import *
from survival_methods import *
######################### SET-UP FRAMEWORK ###################################
# choose this for not using visuals and thus making experiments faster
headless = True
if headless:
os.environ["SDL_VIDEODRIVER"] = "dummy"
experiment_name = 'PLEASE_INSERT_EXPERIMENT_NAME'
if not os.path.exists(experiment_name):
os.makedirs(experiment_name)
# runs simulation
def simulation(env,x):
f,p,e,t = env.play(pcont=x)
return f
# evaluates fitness of every individual in population
def evaluate(x):
return np.array(list(map(lambda y: simulation(env,y), x)))
####################### SET EXPERIMENT PARAMETERS ###########################
np.random.seed(99)
n_hidden_neurons = 10
opponents = [4]
difficulty = 2
# initializes simulation in individual evolution mode, for single static enemy.
env = Environment(experiment_name=experiment_name,
enemies=opponents,
playermode="ai",
player_controller=player_controller(n_hidden_neurons),
enemymode="static",
level=difficulty,
speed="fastest")
# default environment fitness is assumed for experiment
env.state_to_log() # checks environment state
# genetic algorithm params
run_mode = 'train' # train or test
# number of weights for multilayer with 10 hidden neurons
n_vars = (env.get_num_sensors()+1)*n_hidden_neurons + (n_hidden_neurons+1)*5
dom_u = 1 # Max weight for neural network
dom_l = -1 # Min weight for neural network
dist_std = 0.1 # mean of distribution to draw sizes for gene mutation
npop = 200 # Population size
gens = 10 # number of generations
individuals_deleted = 40 # number of individuals killed every generation
num_offspring = individuals_deleted # equal number of offspring to keep constant population size
tournament_size = 20 # Number of individuals taking part in tournamnet selection
sigma = 0.1 # gene mutation probability
#################### PERFORM EXPERIMENT #####################################
start_time = time.time()
# number of times for this experiment to be repeated
experiment_iterations = 10
# create empty arrays to store values for each generation of every experiment iteration
average_fitness_data = np.empty((0, gens+1), float)
max_fitness_data = np.empty((0,gens+1), float)
fitness_std_data = np.empty((0,gens+1), float)
best_solution_data = np.empty((0,n_vars), float)
for iteration in range(experiment_iterations):
# Create Populations, one individual is one row in a matrix
population = np.random.uniform(dom_l, dom_u, (npop, n_vars))
# find fitness of each member of the initial population
fit_pop = evaluate(population)
# store population size to later analyze if remaining constant
pop_size = [len(fit_pop)]
# find the index of the fitest individual
best_solution_index = np.argmax(fit_pop)
# find the fitness of the best solution
fitness_of_best_solution = [fit_pop[best_solution_index]]
# find the mean fitness of the population
mean = [np.mean(fit_pop)]
# find the standard deviation in fitness of the population
std = [np.std(fit_pop)]
for iteration in range(gens):
# empty matrix for children such that they don't take part in
# reproduction of this cycle
children = np.empty((0,n_vars), float)
# create offspring in 2 ways i.e. pure mutation and recombination
#followed by mutation
for i in range(int(num_offspring/2)):
parent_1 = tournament_selection(population, fit_pop, tournament_size)
parent_2 = tournament_selection(population, fit_pop, tournament_size)
if i % 2 == 0:
child_1, child_2 = simple_arithmetic_recombination(parent_1, parent_2)
child_1 = mutation(child_1, sigma, dist_std)
child_2 = mutation(child_2, sigma, dist_std)
else:
child_1 = mutation(parent_1, sigma, dist_std)
child_2 = mutation(parent_2, sigma, dist_std)
# append each child to children array
children = np.append(children, np.array([child_1]), axis=0)
children = np.append(children, np.array([child_2]), axis=0)
# append all offspring of this generation to population
population = np.vstack([population, children])
# evaluate population
fit_pop = evaluate(population)
# kill certain number of worst individuals
population, fit_pop = kill__x_individuals(population, fit_pop, individuals_deleted)
# evaluate whole population and store values
pop_size.append(len(fit_pop))
best_solution_index = np.argmax(fit_pop)
fitness_of_best_solution.append(fit_pop[best_solution_index])
mean.append(np.mean(fit_pop))
std.append(np.std(fit_pop))
average_fitness_data = np.append(average_fitness_data, [np.array(mean)], axis=0)
max_fitness_data = np.append(max_fitness_data, [np.array(fitness_of_best_solution)], axis=0)
fitness_std_data = np.append(fitness_std_data, [np.array(std)], axis=0)
best_solution_data = np.append(best_solution_data, [np.array(population[best_solution_index][:])], axis=0)
end_time = time.time()
execution_time = ((end_time-start_time)/60)/60
print("Runtime was ", execution_time, " hours")
##################### Save Data in Files ####################################
def save_file(data, file_name, experiment_name, cols=True, rows=True):
# Save the data into a dataframe and save in csv file
df = pd.DataFrame(data)
if cols == True:
columns = ['Generation_'+str(i+1) for i in range(gens+1)]
df.columns = columns
if rows == True:
rows = ['Trial_'+str(i+1) for i in range(experiment_iterations)]
df.index = rows
df.to_csv(experiment_name+'/'+experiment_name+file_name)
return
# One file to store set-up
set_up_dict = {
"Population size": npop,
"Generations": gens,
"Killed per generation": individuals_deleted,
"Offspring number": num_offspring,
"Tournament size": tournament_size,
"Gene mutation probability": sigma,
"Enemies": opponents,
"Level": difficulty,
"Iterations:":experiment_iterations,
"Experiment Name": experiment_name,
"Execution Time": execution_time
}
save_file(set_up_dict, '_set_up.csv', experiment_name, cols=False, rows=False)
# One file for mean fitness, max fitness, standard deviation and best solution
save_file(average_fitness_data, '_mean_fitness.csv', experiment_name)
save_file(max_fitness_data, '_max_fitness.csv', experiment_name)
save_file(fitness_std_data, '_std_fitness.csv', experiment_name)
save_file(fitness_std_data, '_std_fitness.csv', experiment_name)
save_file(best_solution_data, '_best_solution.csv', experiment_name, cols=False)