GAにおけるエリート保存戦略について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
たろたろす

GAにおけるエリート保存戦略について

#1

投稿記事 by たろたろす » 10年前

以前、「「nullreferenceexceptionはハンドルされませんでした」の意味と改善方法」というタイトルで質問させていただいたものです。
現在質問させていただいたこともふまえて、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か月程度の未熟者です。
  また、載せたプログラムは、第一世代から、第二世代までの処理です。

根本的なところから誤りがあるかもしれませんが、回答を頂けると助かります。

たろたろす

Re: GAにおけるエリート保存戦略について

#2

投稿記事 by たろたろす » 10年前

連続で書き込んですみません。

もう少し調べたところ、どうやらElite個体がどれかの個体と交叉しているようです。
ですが、まだ解決していません。
回答を頂けると助かります。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: GAにおけるエリート保存戦略について

#3

投稿記事 by みけCAT » 10年前

参照型のデータを代入しても参照が代入されるだけで、実体は同じものを指しています。
したがって、この場合Individual[0]を書き換えるとEliteも書き換わるのだと思います。
GeneTypeをclassではなくstructで宣言し、値型にすると改善するかもしれません。(テストしてません)

値型と参照型 (C# によるプログラミング入門)
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

たろたろす

Re: GAにおけるエリート保存戦略について

#4

投稿記事 by たろたろす » 10年前

回答ありがとうございます。
参照型であるclassを用いたたことが原因だったのですね。
ありがとうございます。

ご指摘いただいたように、structを用いて書き直してみたのですが、構造体の場合だとクラスで書いていた時のように、

public string[] Gene = new string[16];
public int Fitness = 0;

のように、Geneの配列数や、Fitnessの値を設定できませんでした。
Geneの配列数を設定していないため当たり前かもしれませんが、デバッグを行うと、Individual.Gene[j] = Note[RandomNumber];の部分で、
「nullreferenceexceptionはハンドルされませんでした」というメッセージが返ってきます。

コード:

 
using System;

public struct GeneType
{
    public string[] Gene ;//遺伝子長16の遺伝子を格納する配列
    public int Fitness ;//個体の適応度を格納する変数
}

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 = 20;//個体数

        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];
                }
            }
 
そこで、コンストラクタを用いた方法などを調べたのですが、今一つ理解できない状態でいます。
このような場合、どのようにしたらGeneの配列数や、Fitnessの値をあらかじめ設定しておくことができるのでしょうか?
(載せたプログラムは初期集団の生成までです)

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: GAにおけるエリート保存戦略について

#5

投稿記事 by みけCAT » 10年前

たろたろす さんが書きました:このような場合、どのようにしたらGeneの配列数や、Fitnessの値をあらかじめ設定しておくことができるのでしょうか?
コンストラクタを使うといいかもしれません。
ただし、構造体の場合明示的な引数なしのコンストラクタは作れないらしいです。

コード:

 
using System;

public struct GeneType
{
    public string[] Gene ;//遺伝子長16の遺伝子を格納する配列
    public int Fitness ;//個体の適応度を格納する変数
    public GeneType(int geneNumber, int Fitness = 0) {
        this.Gene = new string[geneNumber];
        this.Fitness = Fitness;
    }
}

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 = 20;//個体数

        GeneType[] Individual = new GeneType[indNumber];

            //初期集団の生成
            for (int i = 0; i < indNumber; i++)
            {
                Individual[i] = new GeneType(geneNumber);
                for (int j = 0; j < geneNumber; j++)
                {
                    int RandomNumber = random.Next(Note.Length);
                    Individual[i].Gene[j] = Note[RandomNumber];
                }
            }
 
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

たろたろす

Re: GAにおけるエリート保存戦略について

#6

投稿記事 by たろたろす » 10年前

回答ありがとうございます。

ご指摘いただいた通り、コンストラクタを用いて試してみたのですが、
デバッグを行うと上のプログラムの36行目の

Individual.Gene[j] = Note[RandomNumber];

の部分ででやはり、「nullreferenceexceptionはハンドルされませんでした」というメッセージが返ってきます。
ちなみに、あまり深く考えず下のコードの修正点のコードを加えたところ、デバッグでエラーは起こりませんでした。
しかし、Geneの中身を出力してみると何も格納されていませんでしたが…
どうしたらうまくこのエラーから抜け出せるのでしょうか?
何度も何度も質問して申し訳ありません。

コード:

using System;

public struct GeneType
{
    public string[] Gene ;//遺伝子長の遺伝子を格納する配列
    public int Fitness ;//個体の適応度を格納する変数

    public GeneType(int geneNumber, int Fitness = 0)
    {
        this.Gene = new string[geneNumber];
        this.Fitness = Fitness;
    }
}

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 = 20;//個体数

        GeneType[] Individual = new GeneType[indNumber];

            //初期集団の生成
            for (int i = 0; i < indNumber; i++)
            {
                Individual[i] = new GeneType();
                for (int j = 0; j < geneNumber; j++)
                {
                    Individual[i].Gene= new string[geneNumber];//<----------------------------修正点!!
                    int RandomNumber = random.Next(Note.Length);
                    Individual[i].Gene[j] = Note[RandomNumber];
                }
            }
 

たろたろす

Re: GAにおけるエリート保存戦略について

#7

投稿記事 by たろたろす » 10年前

何度も何度もすみません。

下のプログラムの修正点の箇所にコードを書きくわえたところ、次世代にエリート個体が受け継がれているようでした。
しかし、自分でもよくわからないままなんとなく書き加えてしまったコードです。
このコードを書きくわえることで一体なぜエリート個体がうまく次世代に受け継がれたのでしょうか。
本当にうまくいっているのかはわかりませんが…

コード:

using System;

public struct GeneType
{
    public string[] Gene ;//遺伝子長の遺伝子を格納する配列
    public int Fitness ;//個体の適応度を格納する変数

    public GeneType(int geneNumber, int Fitness = 0)
    {
        this.Gene = new string[geneNumber];
        this.Fitness = Fitness;
    }
}

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 = 20;//個体数
        //int Generation = 100;//世代数

        GeneType[] Individual = new GeneType[indNumber];

            //初期集団の生成
            for (int i = 0; i < indNumber; i++)
            {
                Individual[i].Gene = new string[geneNumber];//<----------------------------修正点!!
                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];
            }

            Console.WriteLine("1世代目");

            for (int i = 0; i < indNumber; i++)
            {
                for (int j = 0; j < geneNumber; j++)
                {
                    Console.Write("{0}", Individual[i].Gene[j]);
                }
                Console.WriteLine("\n{0}", Individual[i].Fitness);
            }
            
           
            //トーナメント選択
            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 トーナメント選択

            

            //交叉
            int n = Individual.Length;

            GeneType Prov = new GeneType();

            //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].Gene = new string[geneNumber];//<-------------------------------修正点!!
                    int CrossPoint = 5;

                    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 適応度計算

            Console.WriteLine("2世代目");

            for (int i = 0; i < indNumber; i++)
            {
                for (int j = 0; j < geneNumber; j++)
                {
                    Console.Write("{0}", Individual[i].Gene[j]);
                }
                Console.WriteLine("\n{0}", Individual[i].Fitness);
            }
            
    }
}

 

たろたろす

Re: GAにおけるエリート保存戦略について

#8

投稿記事 by たろたろす » 10年前

すみません。
上のレスは気にしないでください。
やはりうまくエリート保存できていませんでしたので。
申し訳ありません。

たろたろす

Re: GAにおけるエリート保存戦略について

#9

投稿記事 by たろたろす » 10年前

値型であるstructを用い、デバッグを行ってもエラーが返ってこないように修正しましたが、
やはり交叉処理の前後でエリート個体の中身が他の個体と交叉してしまっているようです。
どのように修正したらエリート個体の中身が変化することなく保持しておくことができるのでしょうか?
何度も申し訳ありませんが、回答していただけると非常に助かります。

たろたろす

Re: GAにおけるエリート保存戦略について

#10

投稿記事 by たろたろす » 10年前

ソースコードを張り忘れていました。
回答を頂けると助かります。

コード:

 
using System;

public struct GeneType
{
    public string[] Gene;//遺伝子長の遺伝子を格納する配列
    public int Fitness;//個体の適応度を格納する変数

    public GeneType(int geneNumber, int Fitness = 0)
    {
        this.Gene = new string[geneNumber];
        this.Fitness = Fitness;
    }
}

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 = 20;//個体数
        //int Generation = 100;//世代数

        GeneType[] Individual = new GeneType[indNumber];

        //初期集団の生成
        for (int i = 0; i < indNumber; i++)
        {
            Individual[i] = new GeneType(geneNumber);
            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];
        }
        //End ob 初期集団のエリート個体の選択

        //トーナメント選択
        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(geneNumber);

        for (int i = 0; i < indNumber; i += 2)
        {
            int CrossPoint = 5;

            for (int j = 0; j < CrossPoint; j++)
            {
                Temp.Gene[j] = Individual[i].Gene[j];
                Individual[i].Gene[j] = Individual[i + 1].Gene[j];
                Individual[i + 1].Gene[j] = Temp.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 突然変異
        
        Console.WriteLine("2世代目");

        for (int i = 0; i < indNumber; i++)
        {
            for (int j = 0; j < geneNumber; j++)
            {
                Console.Write("{0}", Individual[i].Gene[j]);
            }
            Console.WriteLine("\n適応度={0}", Individual[i].Fitness);
        }

    }
}
 

閉鎖

“C言語何でも質問掲示板” へ戻る