最近juliaなるプログラミング言語を見つけ、面白そうだったので勉強を始めました。
今回はその一つとして遺伝的アルゴリズムでOneMax問題を最適していきます
Juliaのwiki
https://ja.wikipedia.org/wiki/Julia_(プログラミング言語)
###初期世代生成
leng = 100
population = 100
mutationRate = 0.1
genelation = 10
function init()
genom::Array{Int8, 2} = rand(0:1, leng, population)
return genom
end
最初の世代は0と1の完全にランダムな配列で生成します。
配列の要素は0か1しか使わないので、Int8でデータ量を節約してます。
###個体の選択
function choice(genom::Array{Int8, 2})
X::Int64 = argmax(sum(genom, dims=2))[1]
Y::Int64 = 0
while true
Y = rand(1:population)
if Y != X
break
end
end
return genom[X, :], genom[Y, :]
end
この関数では、最も優秀な遺伝子Xとランダムに選択された遺伝子Yの
配列を返り値としています。Yのランダム選択部分は1:populationの配列かX番目の値を削除して、その中からランダムに選択する方法もありましたが、pop!の使い方がよく分からなかったのでこうなりました。
###交差
function crossover(X::Array{Int8, 1}, Y::Array{Int8, 1})
genom::Array{Int8, 1} = []
append!(genom, X)
append!(genom, Y)
for i in 1:population-2
cut = rand(2: leng-1)
append!(genom, X[1: cut])
append!(genom, Y[cut+1: leng])
end
return reshape(genom, leng * population)
end
交差は一点交差を使い、返り値はこの後の突然変異のためにleng * populationのサイズの一次元配列にreshapeして返します
###突然変異
function mutation(genom::Array{Int8, 1})
for i in 1: leng * population
if rand() < mutationRate
genom[i] = 1 - genom[i]
end
end
return reshape(genom, leng, population)
end
先ほど一次配列にしたものを受け取ってfor文で全ての要素を参照していきmutationRateの確率で
1と0を反転させてます。
ここだけではないですが、もっとスマートな書き方にできそな所が多々ありますね…
もし修正やアドバイス等ありましたらコメントの程お願いします。
###main関数
function main()
local genom = init()
for i in 1: genelation
X, Y = choice(genom)
genom = crossover(X, Y)
genom = mutation(genom)
println("gen: ", i)
print("avg: ")
println(sum(genom) / (leng * population))
print("max: ")
println(sum(X) / leng)
println("")
end
end
あとは作った関数を組み立てて完成です。
できあがたコードはgithubのリンクを貼っておきます↓
https://github.com/AokiMasataka/One-max/blob/master/OneMax.jl