-
Notifications
You must be signed in to change notification settings - Fork 0
/
population.rb
192 lines (169 loc) · 4.99 KB
/
population.rb
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
# Atributes
# id: int
# number_of_individuals: int
# individuals: Individual
load 'individual.rb'
# Population
class Population
attr_reader :id, :number_of_individuals, :individuals, :fitness
@@last_id = 0
def initialize(number_of_individuals, type_data, info_numbers, crossover_taxa, mutation_taxa, number_of_geration, lim_inf = 0, lim_sup = 1)
@@last_id += 1
@id = @@last_id
@number_of_individuals = number_of_individuals
@type_data = type_data
@info_numbers = info_numbers
@mutation_taxa = mutation_taxa
@crossover_taxa = crossover_taxa
@number_of_geration = number_of_geration
@diversity = []
@fitness_list = []
@bests_individuals = []
@average_fitness = []
@individulas_to_populate = []
@new_sequences = []
@individuals = Array.new(@number_of_individuals) do
Individual.new(type_data, info_numbers, lim_inf, lim_sup)
end
end
def run
index = 0
if @number_of_geration == 0
evoluate
while(@best_individual.fitness_value != 1) do
evoluate
p "#{index} - #{@best_individual.fitness_value}"
index += 1
# p "Best: #{@best_individual.informations} : #{@best_individual.fitness_value}"
end
else
@number_of_geration.times do
p index
index += 1
evoluate
# p "Best: #{@best_individual.informations} : #{@best_individual.fitness_value}"
end
end
p "Best: #{@best_individual.informations} : #{@best_individual.fitness_value}"
gen_logs
gen_graphics
end
def gen_graphics
system("python gen_graphics.py")
end
def gen_logs
# escrevendo @diversity
system("mkdir -p logs")
File.open('logs/log_diversity', 'w') do |f|
@diversity.each do |line|
f.puts line
end
end
# escrevendo @bests_individuals
File.open('logs/log_bests_individuals_fitness', 'w') do |f|
@bests_individuals.map{|item| item.fitness_value}.each do |line|
f.puts line
end
end
# escrevendo @average_fitness
File.open('logs/log_average_fitness', 'w') do |f|
@average_fitness.each do |line|
f.puts line
end
end
end
private
def evoluate
@diversity += [calculate_diversity]
calculate_fitness_of_population
select_best_individual
change_new_individuals
crossover_uniforme
mutation_bit_flip
individuals[rand(0...@number_of_individuals)] = @best_individual
end
def mutation_bit_flip
index = 0
@new_sequences.each do |new_sequence|
for i in 0...@info_numbers
a = rand(0.to_f..1.to_f)
if a < @mutation_taxa
new_sequence[i] = (new_sequence[i] - 1).abs
end
end
individuals[index] = Individual.new(@type_data, @info_numbers, @lim_inf, @lim_sup, new_sequence)
index +=1
end
end
def crossover_uniforme
@new_sequences = []
for i in 0...@number_of_individuals
@new_sequences += [cruzate(i, (i+1) % @number_of_individuals)]
end
end
def cruzate(index_1, index_2)
new_sequence = []
for i in 0...@info_numbers
new_sequence += [rand(0.to_f..1.to_f) < @crossover_taxa ? @individulas_to_populate[index_1].informations[i] : @individulas_to_populate[index_2].informations[i]]
end
new_sequence
end
def select_best_individual
@best_individual = individuals[0]
@individuals.each do |individual|
@best_individual = individual if individual.fitness_value > @best_individual.fitness_value
end
@bests_individuals += [@best_individual]
@average_fitness += [@fitness_list.inject(:+) / Float(@number_of_individuals)]
end
def calculate_diversity
calculate_centroid_values
hamming_distance
end
def hamming_distance
indice = 0
@individuals.each do |individual|
individual.informations.each do |information|
indice += (information - individual.centroid_value) ** 2
end
end
indice
end
def calculate_centroid_values
@individuals.each do |individual|
individual.calculate_centroid_value
end
end
def calculate_fitness_of_population
@individuals.each do |individual|
individual.calculate_fitness_value
end
@fitness_list = individuals.map { |item| item.fitness_value }
end
def change_new_individuals
create_roulette
@individulas_to_populate = []
for i in 1...@number_of_individuals
@individulas_to_populate += [@individuals[change_individual_index]]
end
@individulas_to_populate += [@best_individual]
end
def create_roulette
@roulette = []
total_fitness = @fitness_list.inject(:+)
total = 0
@fitness_list.each do |fitness|
total += (fitness / total_fitness)
@roulette += [total]
end
end
def change_individual_index
a = rand(0.to_f..1.to_f)
index = 0
@roulette.each do |item|
return index if item > a
index =+ 1
end
return index
end
end