遗传算法 C# 实现

笔者最近研究生课题研究一点与优化相关的内容,调研遗传算法觉得很合适(遗传算法此处不过多介绍),但网上都是matlab上面的实现方法,虽然很简单,但我要用在c#系统上面,就打算自己写一个,中间遇到了很多坑,千言万语汇成一句:写算法千万别用c#

话不多说直接上代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace GAtest
{
    public class GA
    {
        //定义种群大小、最大迭代次数、交叉概率和变异概率
        private int populationSize = 30;
        private int maxIterations = 100;
        private double crossoverProbability = 0.7;
        private double mutationProbability = 0.1;
        private int inputSize = 1;//要优化的参数个数

        //定义优化函数
        private double Evaluate(double x)
        {
            return x+10*Math.Sin(5*x)+ 7 * Math.Cos(4 * x);
        }

        //定义个体类
        class Individual
        {
            public double[] genes;//参数列表,此处例子为单参数优化
            public double fitness;//适应度值
            public List<int[]> genesCoding;//基因编码
            public Individual(double[] genes, double fitness, List<int[]> genesCoding)
            {
                this.genes = genes;
                this.fitness = fitness;
                this.genesCoding = genesCoding;
            }
        }

        //生成初始种群
        private Individual[] InitializePopulation()
        {
            Random rand = new Random(GetRandomSeed());
            Individual[] population = new Individual[populationSize];

            for (int i = 0; i < populationSize; i++)
            {
                double[] genes = new double[inputSize];

                //确定每个值的范围
                genes[0] = rand.NextDouble() * 20 - 10; //随机生成[-10,10)之间的实数
                //genes[1] = rand.NextDouble() * 4 + 1; //随机生成[1,5)之间的实数

                List<int[]> genesCoding = GenesCoding(genes);//将值转化成编码
                double fitness = Evaluate(genes[0]);
                population[i] = new Individual(genes, fitness, genesCoding);
            }

            return population;
        }
        //编码
        public List<int[]> GenesCoding(double[] individual)
        {
            List<int[]> genesCoding = new List<int[]>();
            //--------第一个参数----------范围是[-10,10]
            int value = (int)((individual[0] + 10) / (20 / (Math.Pow(2, 20) - 1)));
            int[] binaryArray = new int[20]; // 用于存储二进制数组
            int j = binaryArray.Length - 1; // 数组下标从右向左开始
            while (value > 0 && j >= 0)
            {
                binaryArray[binaryArray.Length - 1-j] = value % 2;
                value /= 2;
                j--;
            }
            genesCoding.Add(binaryArray);
            --------第二个参数----------范围是[1,5]
            //value = (int)((individual[1] - 1) / (4 / (Math.Pow(2, 10) - 1)));
            //binaryArray = new int[10]; // 用于存储二进制数组
            //j = binaryArray.Length - 1; // 数组下标从右向左开始
            //while (value > 0 && j >= 0)
            //{
            //    binaryArray[j--] = value % 2;
            //    value /= 2;
            //}
            //genesCoding.Add(binaryArray);

            return genesCoding;
        }

        private List<int[]> GenesCoding1(Individual individual)
        {
            List<int[]> genesCoding = new List<int[]>();

            //genesCoding.Add()
            return genesCoding;
        }

        //解码
        public double[] GenesEnconding(List<int[]> genesCoding)
        {
            double[] genes = new double[genesCoding.Count];
            //--------第一个参数----------范围是[-10,10]
            int value = 0;
            for (int i = 0; i < genesCoding[0].Length; i++)
            {
                value += genesCoding[0][i] * (int)Math.Pow(2, i);
            }
            genes[0] = -10 + value * 20 / (Math.Pow(2, 20) - 1);
            //--------第一个参数----------范围是[1,5]
            //value = 0;
            //for (int i = 0; i < genesCoding[1].Length; i++)
            //{
            //    value += genesCoding[1][genesCoding[0].Length - i - 1] * (int)Math.Pow(2, i);
            //}
            //genes[1] = 1 + value * 5 / (Math.Pow(2, 10) - 1);

            return genes;
        }


        //选择操作
        private Individual Selection(Individual[] population)
        {
            Individual[] input = population;
            double sumFitness = 0;

            //计算种群适应度之和
            for (int i = 0; i < populationSize; i++)
            {
                sumFitness = sumFitness + input[i].fitness;
            }
            Random rand = new Random(GetRandomSeed());
            //轮盘赌选择
            double r = rand.NextDouble() * sumFitness; //生成0,1的双精度浮点数
            double tmpSum = 0;
            
            for (int i = 0; i < populationSize; i++)
            {
                tmpSum = tmpSum + input[i].fitness;

                if (tmpSum >= r)
                {
                    Individual output = new Individual(input[i].genes,input[i].fitness, input[i].genesCoding);
                    return output;
                }
            }
            Individual output1 = new Individual(input[3].genes, input[3].fitness, input[3].genesCoding);
            return output1;
        }



        //交叉操作
        private Individual[] Crossover(Individual parent1,  Individual parent2)
        {
            Individual[] result = new Individual[2];
            result[0] = new Individual(parent1.genes, parent1.fitness, parent1.genesCoding);
            result[1] = new Individual(parent2.genes, parent2.fitness, parent2.genesCoding);
            Random rand = new Random(GetRandomSeed());
            if (rand.NextDouble() > crossoverProbability)
            {
                return result;
            }

            for (int j = 0; j < parent1.genes.Length; j++)
            {
                rand = new Random(GetRandomSeed());
                int geneLength = parent1.genesCoding[j].Length;
                //随机生成交叉点
                int crossoverPoint = rand.Next(geneLength);
                rand = new Random(GetRandomSeed());
                //随机生成交叉长度
                int crossLenth = rand.Next(geneLength - crossoverPoint);
                //交叉
                for (int i = crossoverPoint; i < crossoverPoint + crossLenth; i++)
                {
                    result[0].genesCoding[j][i] = parent2.genesCoding[j][i];
                    result[1].genesCoding[j][i] = parent1.genesCoding[j][i];
                }
            }
            result[0].genes = GenesEnconding(result[0].genesCoding);
            result[1].genes = GenesEnconding(result[1].genesCoding);
            return result;
        }

        //变异操作,单点变异
        private Individual Mutation(Individual input)
        {
            Random rand = new Random(GetRandomSeed());
            double b = rand.NextDouble();
            Individual output = new Individual(input.genes, input.fitness, input.genesCoding);
            if (b > mutationProbability)
            {
                return output;
            }

            for (int j = 0; j < output.genes.Length; j++)
            {
                rand = new Random(GetRandomSeed());
                int geneLength = output.genesCoding[j].Length;
                //随机生成变异点
                int mutationPoint = rand.Next(geneLength);
                //变异
                output.genesCoding[j][mutationPoint] = output.genesCoding[j][mutationPoint] == 0 ? 1 : 0;
            }
            output.genes = GenesEnconding(output.genesCoding);
            return output;
        }

        //遗传算法主体
        public void Run()
        {
            Individual[] population = InitializePopulation();
            int iteration = 0;
            double[] sumCount = new double[maxIterations];
            while (iteration < maxIterations)
            {
                Individual[] newPopulation = new Individual[populationSize];
                double sum = 0;
                int maxIndex = 0;//最优值的序号
                double maxValue = 0;//最优值所对应的适应度值
                for(int i = 0; i < populationSize; i++)
                {
                    if(population[i].fitness>maxValue)
                    {
                        maxValue = population[i].fitness;
                        maxIndex = i;
                    }
                    sum += population[i].fitness;
                }
                sumCount[iteration] = sum/ populationSize;//平均适应度
                //生成新种群
                for (int i = 0; i < populationSize; i++)
                {
                    if (i == maxIndex)//精英策略,每一代最优的个体留下来
                    {
                        newPopulation[i] = population[i];
                        continue;
                    }
                    //随机选择父母
                    Individual[] newPop = (Individual[])population.Clone();
                    Individual parent1 = Selection(newPop);
                    Individual parent2 = Selection(newPop);
                    //交叉
                    Individual[] children =  Crossover(parent1,parent2);

                    //变异
                    children[0] = Mutation(children[0]);
                    children[1] = Mutation(children[1]);
                    children[0].fitness = Evaluate(children[0].genes[0]) ;//计算适应度
                    children[1].fitness = Evaluate(children[1].genes[0]);//计算适应度
 
                    newPopulation[i] = children[0].fitness > children[1].fitness ? children[0] : children[1];//选择最优的交叉变异个体
                }
                
                population = (Individual[])newPopulation.Clone();
                iteration++;
                Console.WriteLine("迭代第{0}代,平均适应度为{1}", iteration, sumCount[iteration]);
            }
            //输出最优解
            double bestFitness = double.MinValue;
            double bestGene1 = 0;
            //double bestGene2 = 0;
            for (int i = 0; i < populationSize; i++)
            {
                if (population[i].fitness > bestFitness)
                {
                    bestFitness = population[i].fitness;
                    bestGene1 = population[i].genes[0];
                    //bestGene2 = population[i].genes[1];
                }
            }
            Console.WriteLine("最优解:x = {0},f(x) = {1}", bestGene1, bestFitness);
            
        }
        public static int GetRandomSeed()//随机种子,防止短时间内生成的随机数相同
        {
            byte[] bytes = new byte[4];
            System.Security.Cryptography.RNGCryptoServiceProvider rng = new System.Security.Cryptography.RNGCryptoServiceProvider();
            rng.GetBytes(bytes);
            return BitConverter.ToInt32(bytes, 0);
        }
    }
}

直接运行run()函数即可实现,对环境没有任何要求。

要是多优化问题就需要在初始化个体种群时给genes赋多个值,还需要修改编码函数和解码函数,确定不同的取值范围等。

  • 11
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值