-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathmgga.py
132 lines (112 loc) · 4.68 KB
/
mgga.py
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
#!/usr/bin/python3
import random
import numpy as np
import copy
class MGGA():
def __init__(self, settings, seed = 1283123901319):
# Override default seed if it is in settings
if "seed" in settings.keys():
seed = settings["seed"]
self.seed = seed
random.seed(self.seed)
# Settings
self.population_size = settings["population"]
self.generations = settings["generations"]
self.num_genes = settings["num_of_states"]
self.chromosome_length = settings["chromosome_length"]
self.copy_prob = settings["copy_prob"]
self.crossover_prob = settings["crossover_prob"]
self.mutation_prob = settings["mutation_prob"]
self.percentage_worst = settings["percentage_worst"]
self.tourament_size = settings["tournament_size"]
self.population = []
self.children = []
self.fitness = []
self.count = {}
self.count["mutate"] = 0
self.count["crossover"] = 0
self.count["clone"] = 0
def __summary(self):
total = self.count["crossover"]
total = total + self.count["clone"]
total = total + self.count["mutate"]
per_cross = 100*self.count["crossover"]/total
per_clone = 100*self.count["clone"]/total
per_mutate = 100*self.count["mutate"]/total
print("crossover happened: %f (%f%%)" % (self.count["crossover"],per_cross))
print("clone happened: %f (%f%%)" % (self.count["clone"], per_clone))
print("mutate happened: %f (%f%%)" % (self.count["mutate"], per_mutate))
# purely random mutation
def __mutate(self, chromosome):
selected_gene = random.randint(0,self.chromosome_length-1)
random_gene = random.randint(0,self.num_genes-1)
new_chromosome = copy.deepcopy(chromosome)
new_chromosome[selected_gene] = random_gene
return new_chromosome
# blend the two chromosomes
def __uniform_crossover(self,chromosome1):
rand = random.randint(0,1)
# pick the other parent randomly
chromosome2 = self.population[rand]
child1 = [0]*self.chromosome_length
child2 = [0]*self.chromosome_length
for i in range(self.chromosome_length):
select_parent = random.randint(0,1)
if select_parent == 0:
child1[i] = chromosome1[i]
child2[i] = chromosome2[i]
else:
child1[i] = chromosome2[i]
child2[i] = chromosome1[i]
return [child1,child2]
# copy the chromosome
def __clone(self,chromosome):
return copy.deepcopy(chromosome)
def __random(self):
chromosome = [0]*self.chromosome_length
for i in range(self.chromosome_length):
chromosome[i] = random.randint(0,self.num_genes-1)
return chromosome
def __sample(self,chromosome):
rand = random.random()
if rand <= self.copy_prob:
self.count["clone"] = self.count["clone"] + 1
return self.__clone(chromosome)
elif rand > self.copy_prob and rand <= self.copy_prob + self.mutation_prob:
self.count["mutate"] = self.count["mutate"] + 1
return self.__mutate(chromosome)
else:
self.count["crossover"] = self.count["crossover"] + 1
return self.__uniform_crossover(chromosome)
def fill_population(self):
for i in range(self.population_size):
chromosome = self.__random()
self.population.append(chromosome)
def sample_population(self):
parents = []
for i in range(self.population_size):
tornament_competitors = [0] * self.tornament_size
competitor_fitness = [0] * self.tornament_size
# pick ts individuals
for j in range(self.tornament_size):
rand = random.randint(0,self.chromosome_length-1)
tornament_competitors[j] = self.population[rand]
competitor_fitness[j] = self.fitness[rand]
rand = random.random()
winner = 0
if rand > self.percentage_worst:
winner = tornament_competitors[np.argmax(competitor_fitness)]
# choose max fitness from the competitors
else:
winner = tornament_competitors[np.argmin(competitor_fitness)]
# choose the least fit
parents.append(winner)
# now breed
for i in range(self.population_size):
child = self.__sample(parents[i])
if len(child) < self.chromosome_length:
self.children.append(child[0])
self.children.append(child[1])
else:
self.children.append(child)
self.__summary()