遺伝的アルゴリズムで親の選択後に行う交叉についてPythonで作った.
実装した交叉手法は
・一点交叉
・二点交叉
・突然変異
普通は二点交叉で一点交叉も実現されるため実装するのは片方だけで良いが,
今回はプログラム実装の関係上2種類とも記述してある.
推奨される突然変異の確率はだいたい0.5~1%だが今回は子の数も少ないので確認のため10%にした.
また,交叉の確認のために親は[1,1,1,1,1,1,1,1,1], [0,0,0,0,0,0,0,0,0]を初期値として持っている.
実行結果
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 |
>> 3 8 ('Child1:', [1, 1, 1, 0, 0, 0, 0, 0, 1]) ('Child2:', [0, 0, 0, 1, 1, 1, 1, 1, 0]) >> 6 8 ('Child1:', [1, 1, 1, 0, 0, 0, 1, 1, 1]) ('Child2:', [0, 0, 0, 1, 1, 1, 0, 0, 0]) >> 3 7 ('Child1:', [1, 1, 1, 1, 1, 1, 0, 1, 1]) ('Child2:', [0, 0, 0, 0, 0, 0, 1, 0, 0]) >> 3 4 ('Child1:', [1, 1, 1, 0, 1, 1, 0, 1, 1]) ('Child2:', [0, 0, 0, 1, 0, 0, 1, 0, 0]) >> 1 9 ('mutation!!:', 4) ('Child1:', [1, 0, 0, 1, 1, 0, 1, 0, 0]) ('Child2:', [0, 1, 1, 0, 1, 1, 0, 1, 1]) |
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 |
import random #引数は親のリスト2つ def cross(p1, p2): #子のリスト c1 = list() c2 = list() #交叉点sp1, sp2 sp1 = random.randint(1,9) sp2 = random.randint(1,9) #突然変異確率 mut = random.randint(1,10) #交叉点の小さい方をsp1とする if sp1 > sp2: swap = sp1 sp1 = sp2 sp2 = swap print(sp1) print(sp2) #一点交叉 if sp1 == sp2: for i in range(sp1): c1.append(p1[i]) c2.append(p2[i]) for i in range(sp1,9): c1.append(p2[i]) c2.append(p1[i]) #二点交叉 else: for i in range(sp1): c1.append(p1[i]) c2.append(p2[i]) for i in range(sp1,sp2): c1.append(p2[i]) c2.append(p1[i]) for i in range(sp2,9): c1.append(p1[i]) c2.append(p2[i]) #突然変異 if mut == 5: #変異する子,変異する位置を決定 which = random.randint(1,2) element = random.randint(0,8) print("mutation!!:",element) #ビット反転 if(which == 1): c1[element] = ~c1[element]+2 else: c2[element] = ~c2[element]+2 return c1,c2 if __name__ == "__main__": parent1 = [1,1,1,1,1,1,1,1,1] parent2 = [0,0,0,0,0,0,0,0,0] while True: raw_input(">>") child1, child2 = cross(parent1,parent2) print("Child1:", child1) print("Child2:", child2) parent1 = child1 parent2 = child2 |