GAにおけるエリート保存戦略について
Posted: 2014年11月03日(月) 23:26
以前、「「nullreferenceexceptionはハンドルされませんでした」の意味と改善方法」というタイトルで質問させていただいたものです。
現在質問させていただいたこともふまえて、GAを作っています。
[1] 質問文
[1.1] 自分が今行いたい事は何か
ランダムな文字列を遺伝子として持つ個体について、目的の文字列があった場合、得点を加算し、その得点を個体の評価値とする。
ということをGAで行っています。(評価関数が線形(?)ですし、あまりGAを用いる意味はないと思いますが、練習がてらに)
その中で、エリート保存戦略を行いたいと考えています。
[1.2] どのように取り組んだか(プログラムコードがある場合記載)
[1.3] どのようなエラーやトラブルで困っているか(エラーメッセージが解る場合は記載)
しかし、エリート保存戦略を導入したところ、うまくエリート個体を次の世代に残せていませんでした。
というのも、途中で、Eliteの中身が代わっているようなのです。
調べてみると、交叉処理を行う前と後でEliteの中身が代わっているようです。
[1.4] 今何がわからないのか、知りたいのか
このような場合、どう改善したらうまくエリート個体を次世代に残していくことができるのでしょうか。
[2] 環境
[2.1] OS : Windows
[2.2] コンパイラ名 : VC# 2010 Express
[3] その他
C#は勉強をはじめて3か月程度の未熟者です。
また、載せたプログラムは、第一世代から、第二世代までの処理です。
根本的なところから誤りがあるかもしれませんが、回答を頂けると助かります。
現在質問させていただいたこともふまえて、GAを作っています。
[1] 質問文
[1.1] 自分が今行いたい事は何か
ランダムな文字列を遺伝子として持つ個体について、目的の文字列があった場合、得点を加算し、その得点を個体の評価値とする。
ということをGAで行っています。(評価関数が線形(?)ですし、あまりGAを用いる意味はないと思いますが、練習がてらに)
その中で、エリート保存戦略を行いたいと考えています。
[1.2] どのように取り組んだか(プログラムコードがある場合記載)
using System;
public class GeneType
{
public string[] Gene = new string[16];//遺伝子長の遺伝子を格納する配列
public int Fitness = 0;//個体の適応度を格納する変数
}
class Compose
{
public static void Main()
{
string[] Note = {"休符","ド1","ド#1","レ1","レ#1","ミ1","ファ1","ファ#1","ソ1","ソ#1","ラ1","ラ#1","シ1",
"ド1","ド2", "ド#2","レ2","レ#2","ミ2","ファ2","ファ#2","ソ2","ソ#2","ラ2","ラ#2","シ2",
"ド3","ド#3","レ3","レ#3","ミ3","ファ3"};
Random random = new Random();
int geneNumber = 16;//遺伝子長
int indNumber = 50;//個体数
//int Generation = 100;//世代数
GeneType[] Individual = new GeneType[indNumber];
//初期集団の生成
for (int i = 0; i < indNumber; i++)
{
Individual[i] = new GeneType();//修正点!!
for (int j = 0; j < geneNumber; j++)
{
int RandomNumber = random.Next(Note.Length);
Individual[i].Gene[j] = Note[RandomNumber];
}
}
//各個体ごとの適応度計算
for (int i = 0; i < indNumber; i++)
{
for (int j = 0; j < geneNumber; j++)
{
if (Individual[i].Gene[j] == "休符")
{
Individual[i].Fitness = Individual[i].Fitness + 10;
}
else if (Individual[i].Gene[j] == "レ2")
{
Individual[i].Fitness = Individual[i].Fitness + 10;
}
else if (Individual[i].Gene[j] == "ミ2")
{
Individual[i].Fitness = Individual[i].Fitness + 10;
}
else if (Individual[i].Gene[j] == "ファ#2")
{
Individual[i].Fitness = Individual[i].Fitness + 10;
}
else if (Individual[i].Gene[j] == "ソ2")
{
Individual[i].Fitness = Individual[i].Fitness + 10;
}
else if (Individual[i].Gene[j] == "ラ2")
{
Individual[i].Fitness = Individual[i].Fitness + 10;
}
else if (Individual[i].Gene[j] == "シ2")
{
Individual[i].Fitness = Individual[i].Fitness + 10;
}
else if (Individual[i].Gene[j] == "ド#3")
{
Individual[i].Fitness = Individual[i].Fitness + 10;
}
else
{
Individual[i].Fitness = Individual[i].Fitness + 0;
}
}
}
//End of 適応度計算
//初期集団のエリート個体を選択
GeneType Elite = new GeneType();
for (int i = 1; i < indNumber; i++)
{
if (Individual[0].Fitness < Individual[i].Fitness)
{
Individual[0] = Individual[i];
}
Elite = Individual[0];
}
//トーナメント選択
int t1;
int t2;
GeneType[] ind_New = new GeneType[indNumber];
for (int i = 0; i < indNumber; i++)
{
t1 = random.Next(indNumber);
t2 = random.Next(indNumber);
if (Individual[t1].Fitness > Individual[t2].Fitness)
{
ind_New[i] = Individual[t1];
}
else
{
ind_New[i] = Individual[t2];
}
}
//トーナメント選択を基に個体集合の更新
for (int i = 0; i < indNumber; i++)
{
Individual[i] = ind_New[i];
}
//End of トーナメント選択
//交叉
GeneType Prov = new GeneType();
int n = Individual.Length;
//Individualをシャッフル
while (n > 1)
{
n--;
int i = random.Next(n + 1);
Prov = Individual[i];
Individual[i] = Individual[n];
Individual[n] = Prov;
}
//実際に交叉させる <----------------------------問題点?
GeneType[] Temp = new GeneType[indNumber];
for (int i = 0; i < indNumber; i += 2)
{
Temp[i] = new GeneType();//修正点!!
int CrossPoint = 4;
for (int j = 0; j < CrossPoint; j++)
{
Temp[i].Gene[j] = Individual[i].Gene[j];
Individual[i].Gene[j] = Individual[i + 1].Gene[j];
Individual[i + 1].Gene[j] = Temp[i].Gene[j];
}
}
//End of 交叉 <-----------------------------問題点?
//突然変異
int Mutation = random.Next(0, 100);
for (int i = 0; i < indNumber; i++)
{
for (int j = 0; j < geneNumber; j++)
{
if (Mutation <= 10)
{
int RandomNumber = random.Next(Note.Length);
Individual[i].Gene[j] = Note[RandomNumber];
}
}
}
//End of 突然変異
//エリート個体の挿入
Individual[0] = Elite;
for (int i = 1; i < indNumber; i++)
{
if (Individual[0].Fitness < Individual[i].Fitness)
{
Individual[0] = Individual[i];
}
Elite = Individual[0];
}
//各個体ごとの適応度計算
for (int i = 0; i < indNumber; i++)
{
Individual[i].Fitness = 0;
for (int j = 0; j < geneNumber; j++)
{
if (Individual[i].Gene[j] == "休符")
{
Individual[i].Fitness = Individual[i].Fitness + 10;
}
else if (Individual[i].Gene[j] == "レ2")
{
Individual[i].Fitness = Individual[i].Fitness + 10;
}
else if (Individual[i].Gene[j] == "ミ2")
{
Individual[i].Fitness = Individual[i].Fitness + 10;
}
else if (Individual[i].Gene[j] == "ファ#2")
{
Individual[i].Fitness = Individual[i].Fitness + 10;
}
else if (Individual[i].Gene[j] == "ソ2")
{
Individual[i].Fitness = Individual[i].Fitness + 10;
}
else if (Individual[i].Gene[j] == "ラ2")
{
Individual[i].Fitness = Individual[i].Fitness + 10;
}
else if (Individual[i].Gene[j] == "シ2")
{
Individual[i].Fitness = Individual[i].Fitness + 10;
}
else if (Individual[i].Gene[j] == "ド#3")
{
Individual[i].Fitness = Individual[i].Fitness + 10;
}
else
{
Individual[i].Fitness = Individual[i].Fitness + 0;
}
}
}
//End of 適応度計算
}
}
[1.3] どのようなエラーやトラブルで困っているか(エラーメッセージが解る場合は記載)
しかし、エリート保存戦略を導入したところ、うまくエリート個体を次の世代に残せていませんでした。
というのも、途中で、Eliteの中身が代わっているようなのです。
調べてみると、交叉処理を行う前と後でEliteの中身が代わっているようです。
[1.4] 今何がわからないのか、知りたいのか
このような場合、どう改善したらうまくエリート個体を次世代に残していくことができるのでしょうか。
[2] 環境
[2.1] OS : Windows
[2.2] コンパイラ名 : VC# 2010 Express
[3] その他
C#は勉強をはじめて3か月程度の未熟者です。
また、載せたプログラムは、第一世代から、第二世代までの処理です。
根本的なところから誤りがあるかもしれませんが、回答を頂けると助かります。