-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathmgga.py
126 lines (108 loc) · 4.33 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
#!/usr/bin/python3
import random
import numpy as np
import copy
class MGGA():
def __init__(self, seed = 1283123901319):
self.population_size = 0
self.generations = 0
self.num_genes = 0
self.chromosome_length = 0
self.copy_prob = 0.0
self.crossover_prob = 0.0
self.mutation_prob = 0.0
self.population = []
self.children = []
self.fitness = []
self.seed = seed
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))
def initialise(self):
if self.seed != 0:
random.seed(self.seed)
# 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()