Ejemplo n.º 1
0
        public static void Main(string[] args)
        {
            Gen[] Genetic = new Gen[20]; //その代の遺伝子を格納する.世代が変わるごとに上書き

            Gen MaxGen = new Gen();      //もっとも優秀な遺伝子を保存する

            MaxGen.gene = new bool[10];
            MaxGen.fit  = int.MinValue;


            //初期集団の生成
            for (int i = 0; i < 20; i++)
            {
                Gen data = new Gen();
                data.gene = new bool[10];

                //乱数生成
                byte[] bs = new byte[2];
                System.Security.Cryptography.RNGCryptoServiceProvider rng =
                    new System.Security.Cryptography.RNGCryptoServiceProvider();
                rng.GetBytes(bs);
                var    toint = System.BitConverter.ToInt16(bs, 0);
                string str   = Convert.ToString(toint, 2); //short型で得られた乱数を2進数表記で文字列化
                if (str.Length < 10)                       //2進数の文字列が10文字未満の時先頭に0を追加していく
                {
                    while (str.Length != 10)
                    {
                        str = str.Insert(0, "0");
                    }
                }
                str = str.Substring(str.Length - 10, 10);//10文字以上の時10文字に収まるように大きい桁を切り捨てる

                int count = 0;
                foreach (var num in str)                //Gen構造体のgeneはbool型の配列で表現するため遺伝子が1の場合trueを,0の場合falseを入れる
                {
                    bool b = num == '1' ? true : false; //numが1ならtrueを0ならfalseをbに代入
                    data.gene[count] = b;
                    count++;
                }
                data.fit = Fitness(data.gene); //式に当てはめ結果を保存
                if (MaxGen.fit < data.fit)     //最良の遺伝子を保存
                {
                    MaxGen.fit = data.fit;
                    data.gene.CopyTo(MaxGen.gene, 0);
                }
                Genetic[i] = data;
            }
            Console.WriteLine("___________GA____________");
            for (int i = 0; i < 500; i++)       //500世代回す
            {
                Genetic = Select(Genetic);      //選択

                for (int j = 0; j < 20; j += 2) //交叉
                {
                    Gen[] cross = new Gen[2];
                    cross[0].gene = new bool[10];
                    cross[1].gene = new bool[10];

                    //交叉関数に渡すためにGeneticの値をcrossに値渡しでコピー
                    Genetic[j].gene.CopyTo(cross[0].gene, 0);
                    Genetic[j + 1].gene.CopyTo(cross[1].gene, 0);

                    cross = Crossover(cross[0], cross[1]);//交叉関数の呼び出し

                    //結果をGeneticに保存
                    cross[0].gene.CopyTo(Genetic[j].gene, 0);
                    cross[1].gene.CopyTo(Genetic[j + 1].gene, 0);
                }
                //どの遺伝子を突然変異させるかをランダムで決定する.そのままだと似たランダム値が得られるためシード値を加えより値が散らばるようにする
                int    seed = Environment.TickCount;
                Random r    = new Random(seed + i);
                int    rnd  = r.Next(20);
                Mutation(Genetic[rnd]).gene.CopyTo(Genetic[rnd].gene, 0); //突然変異

                for (int j = 0; j < 20; j++)                              //フィットネスの計算と初期化
                {
                    Genetic[j].fit      = Fitness(Genetic[j].gene);
                    Genetic[j].roulette = 0;
                    if (MaxGen.fit < Genetic[j].fit)//最良の遺伝子を保存
                    {
                        MaxGen.fit = Genetic[j].fit;
                        Genetic[j].gene.CopyTo(MaxGen.gene, 0);
                    }
                }
            }
            Gen last = new Gen();

            last.gene = new bool[10];
            last.fit  = int.MinValue;
            for (int i = 0; i < 20; i++)
            {
                if (last.fit < Genetic[i].fit)
                {
                    last.fit = Genetic[i].fit;
                    Genetic[i].gene.CopyTo(last.gene, 0);
                }
            }
            Console.WriteLine("lastGen.fit : " + last.fit);
            foreach (var n in last.gene)
            {
                Console.Write(n == true ? "1" : "0");
            }
            Console.WriteLine();
            Console.WriteLine(ConvertX(last.gene));

            Console.WriteLine("%%%%%%%%%%%%%%%");
            Console.WriteLine("MaxGene.fit : " + MaxGen.fit);

            foreach (var n in MaxGen.gene)
            {
                Console.Write(n == true ? "1" : "0");
            }
            Console.WriteLine();
            Console.WriteLine(ConvertX(MaxGen.gene));
        }
Ejemplo n.º 2
0
        public static Gen[] Select(Gen[] gene)                          //選択
        {
            var Genetic = gene.OrderByDescending(g => g.fit).ToArray(); //fitの値で良い順にソート

            var roulette = new Gen[10];                                 //下位10個の遺伝子を保存する用

            for (int i = 0; i < 10; i++)                                //Geneticからrouletteにコピー
            {
                roulette[i].fit  = Genetic[i + 10].fit;
                roulette[i].gene = new bool[10];
                for (int j = 0; j < 10; j++)
                {
                    roulette[i].gene[j] = Genetic[i + 10].gene[j];
                }
            }


            double total  = new double();
            double sumfit = new double();

            for (int i = 0; i < 10; i++)//ルーレット選択するために合計値取得
            {
                if (roulette[i].fit > 0.0)
                {
                    total += roulette[i].fit;
                }
            }

            for (int i = 0; i < 10; i++)//適応度の計算,マイナス値とNaNの時は0
            {
                if (roulette[i].fit > 0.0)
                {
                    sumfit += roulette[i].fit / total;//適応度は式の答え/合計値
                    roulette[i].roulette = sumfit;
                }
                else
                {
                    roulette[i].roulette = 0;//NaNやマイナス値はルーレットから除外する
                }
            }
            Random r     = new Random();
            double range = new double();//一つ前の遺伝子のfitの値

            for (int i = 0; i < 10; i++)
            {
                range = 0.0;
                double rnd = r.NextDouble();//どの遺伝子を選択するかの乱数
                for (int j = 0; j < 10; j++)
                {
                    if (range <= rnd && roulette[j].roulette >= rnd)//遺伝子が選択され,コピーする
                    {
                        Genetic[i + 10].fit      = roulette[j].fit;
                        Genetic[i + 10].roulette = roulette[j].roulette;
                        roulette[j].gene.CopyTo(Genetic[i + 10].gene, 0);
                        break;
                    }
                    range = roulette[j].roulette;
                }
            }
            return(Genetic);
        }