-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclass_GeneticAlgorightm.py
221 lines (158 loc) · 8.34 KB
/
class_GeneticAlgorightm.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
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
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
# -*- coding: utf-8 -*-
import random
from class_DAG import DAG
from class_DAG import one_entry_DAG
from class_ClusteredManyCore import ClusteredManyCoreProcesser
from class_Scheduler import Scheduler
from Proposed_GA import Proposed_GA
class Chromosome:
# <コンストラクタ>
def __init__(self, CHROMOSOME_LENGTH):
'''
fitness : 評価値=メイクスパン
gene_list : 遺伝子情報
result_core : プロセッサへの割り当て結果(評価用)
result_node : プロセッサへの割り当て結果(評価用)
'''
self.fitness = -1
self.gene_list = self.init_gene_list(CHROMOSOME_LENGTH)
# <メソッド>
# 遺伝子情報をランダムにセット
def init_gene_list(self, CHROMOSOME_LENGTH):
gene_list = []
for i in range(CHROMOSOME_LENGTH):
gene_list.append(random.randint(0, 1))
return gene_list
class GeneticAlgorithm():
# <コンストラクタ>
def __init__(self, dag, target, num_of_population, mutation_ratio, max_population):
'''
DAG : 評価するDAG
ONE_ENTRY_DAG : DAGに仮想エントリーノードを加えたもの
TARGET : 割り当て対象のプロセッサ
COMM_CORRESPONDENCE : GAの遺伝子と、DAGの通信の対応表
CHROMOSOME_LENGTH : 遺伝子の長さ=DAG内のエッジの数
NUM_OF_POPULATION : 1世代中の個体数
MUTATION_RATIO : 突然変異確率
MAX_POPULATION : 繰り返す世代数
population : 現在の世代
'''
self.DAG = dag
self.ONE_ENTRY_DAG = one_entry_DAG(self.DAG.file_name)
self.TARGET = ClusteredManyCoreProcesser(target.num_of_cluster, target.num_of_core, target.inout_ratio)
self.COMM_CORRESPONDENCE = self.generate_comm_list()
self.CHROMOSOME_LENGTH = self.DAG.num_edge()
self.NUM_OF_POPULATION = num_of_population
self.MUTATION_RATIO = mutation_ratio
self.MAX_POPULATION = max_population
self.population = self.first_population()
self.start_evo()
# <メソッド>
# GAで用いるリストと、DAGの通信の対応表を生成
def generate_comm_list(self):
comm_list = []
for i in range(self.DAG.num_of_node):
for j in range(self.DAG.num_of_node):
if (self.DAG.edge[i][j] != 0): # エッジがあれば
comm_list.append(str(i) + "_" + str(j)) # i_j : Ti と Tj の通信
return comm_list
# 第一世代を生成
def first_population(self):
population = []
for i in range(self.NUM_OF_POPULATION):
individual = Chromosome(self.CHROMOSOME_LENGTH)
population.append(individual)
return population
# 進化開始
def start_evo(self):
for i in range(self.MAX_POPULATION):
offspring = self.selected_by_elite() # エリート選択
# 交叉
children = []
for j in range(self.NUM_OF_POPULATION - len(offspring)): # 不足分
# エリートからランダムに2つの遺伝子を取り出し、1点交叉
gene1 = random.choice(offspring)
gene2 = random.choice(offspring)
child1, child2 = self.single_point_crossover(gene1, gene2)
children.append(child1)
children.append(child2)
offspring.extend(children)
self.mutate(offspring) # 突然変異
self.population = offspring # 世代交代
self.calc_fitness() # 評価値計算
# 結果の出力
print("-- 第{}世代 --" .format(i + 1))
self.print_population_ave
best_chromosome = self.return_best_chromosome()
print("<最も優れていた個体>")
print("メイクスパン: {}" .format(best_chromosome.fitness))
self.print_match_ratio(best_chromosome)
# 現在の世代の遺伝子をすべて評価
def calc_fitness(self):
for chromosome in self.population:
target = ClusteredManyCoreProcesser(self.TARGET.num_of_cluster, self.TARGET.num_of_core, self.TARGET.inout_ratio)
scheduling_list = Proposed_GA(self.ONE_ENTRY_DAG, self.COMM_CORRESPONDENCE, chromosome.gene_list, self.TARGET.inout_ratio)
scheduler = Scheduler(scheduling_list, self.DAG, target)
scheduler.schedule()
chromosome.result_core = scheduler.result_core
chromosome.result_node = scheduler.result_node
chromosome.fitness = scheduler.makespan()
# エリート選択
def selected_by_elite(self):
elite = sorted(self.population, key=lambda x: x.fitness)
return elite[:self.NUM_OF_POPULATION // 2] # 1世代の遺伝子数//2分残す
# 一点交叉
def single_point_crossover(self, gene1, gene2):
gene1_after_cross = Chromosome(self.CHROMOSOME_LENGTH)
gene2_after_cross = Chromosome(self.CHROMOSOME_LENGTH)
cross_point = random.randint(0, self.CHROMOSOME_LENGTH) # 入れ替える点を設定
gene1_after_cross.gene_list = gene1.gene_list[cross_point:] + gene2.gene_list[:cross_point]
gene2_after_cross.gene_list = gene2.gene_list[cross_point:] + gene1.gene_list[:cross_point]
return gene1_after_cross, gene2_after_cross
# 突然変異
def mutate(self, population):
for i in range(1, len(population)): # 最もエリート以外が対象
for j in range(len(population[i].gene_list)):
if(random.random() < self.MUTATION_RATIO):
population[i].gene_list[j] = abs(population[i].gene_list[j] - 1) # 0<->1
# 最もメイクスパンが小さい染色体を返す
def return_best_chromosome(self):
gene_list_sorted = sorted(self.population, key=lambda x: x.fitness)
return gene_list_sorted[0]
# 現在の世代の fitness 平均を表示
def print_population_ave(self):
sum = 0
for i in range(self.NUM_OF_POPULATION):
sum += self.population[i].fitness
ave = sum / self.NUM_OF_POPULATION
print("平均値: {}" .format(ave))
# 遺伝子情報と実際の割り当ての一致度を出力
def print_match_ratio(self, chromosome):
# 遺伝子情報によって、クラスタ外通信として計算したエッジを出力
gene_list_out = []
for i in range(self.CHROMOSOME_LENGTH):
if(chromosome.gene_list[i] == 1):
gene_list_out.append(self.COMM_CORRESPONDENCE[i])
#print("遺伝子情報によって、クラスタ外通信として計算したエッジ: \n{}" .format(gene_list_out))
# 割り当て後の、実際にクラスタ外通信が行われたエッジを出力
allocate_out = []
for n in range(self.DAG.num_of_node):
for pred_n in self.DAG.pred[n]:
if(chromosome.result_node[pred_n][0] != chromosome.result_node[n][0]):
allocate_out.append(str(pred_n) + "_" + str(n))
#print("割り当て後の、実際にクラスタ外通信が行われたエッジ: \n{}" .format(allocate_out))
# allocate_out をもとに、01のリストを作成(遺伝子情報と比較するため)
allocate_list = [0] * self.CHROMOSOME_LENGTH
for i in range(len(self.COMM_CORRESPONDENCE)):
if(self.COMM_CORRESPONDENCE[i] in allocate_out):
allocate_list[i] = 1
match = 0
for i in range(self.CHROMOSOME_LENGTH):
if(chromosome.gene_list[i] == allocate_list[i]):
match += 1
match_ratio = match / self.CHROMOSOME_LENGTH * 100
print("遺伝子情報と実際の割り当ての一致度: {:.1f}%" .format(match_ratio))
if __name__ == "__main__":
dag = DAG("new_50_0")
target = ClusteredManyCoreProcesser(2, 3, 3)
ga = GeneticAlgorithm(dag, target, 8, 0.1, 10000)