• 遗传算法的简单应用-求解方程


    上篇初识遗传算法讲述了遗传算法的基本思想,这篇博客就用遗传算法求解方程。

    具体的如下:

    求解方程 -x^3+7*x+13=0 在[3,4]区间的解,解精确到0.001,交叉概率0.7

    变异概率0.01,迭代次数为100,字符编码长度为10(二进制编码)

    首先简单的分析一下:

    1、编码与解码

    题目要求的是采用二进制的编码方式来实现,既然已经编码了,自然就需要解码,给定的10

    位二进制编码表示的区间范围就是0~1023,题目的区间是[3,4]很自然的就能想到10位二进

    制编码中的0表示是就是[3,4]中的3,1023表示的就是[3,4]中的4,所以,每个二进制对应的

    十进制就是((10位二进制对应的十进制数/1023)+3),这个就是解码后的在区间[3,4]中的具体值。

    2、适应度函数

     这里取的适应度函数是方程绝对值的倒数,即f=1/(|-x^3+7*x+13|)

    3、选择算子

    确定选择比例,采用轮盘赌算法。

            /// <summary>
            /// 模拟轮盘赌选择算法
            /// 思路:1.求适应度的总和;2.计算每个个体适应度所占的比例(除第一个之外,其他的都是叠加);
            /// 3.在0~1产生随机数,这个随机数所在的区间,就是要选择的个体
            /// </summary>
            /// <returns>选择出来的优秀个体</returns>
            static List<int> RWS(List<double> list)
            {
                List<int> select = new List<int>();
                List<double> p = new List<double>();
                double sum = list.Sum()/*适应度之和*/, temp = 0/*临时变量*/;
                foreach (var item in list)
                {
                    temp += (item / sum);//叠加
                    p.Add(temp);//概率
                }
                int i, j;
                for (i = 0; i < p.Count; i++)
                {
                    temp = rd.NextDouble();//0~1的随机数
                    for (j = 0; j < p.Count; j++)
                    {
                        if (j == 0 && temp < p[0])
                        {
                            select.Add(0);
                        }
                        else if (temp < p[j] && temp >= p[j - 1])
                        {
                            select.Add(j);
                        }
                    }
                }           
                return select;
            }    
    View Code

    4、交配算子

    随机产生交配位,交换两个染色体的部分基因。

            /// <summary>
            /// 交叉过程个体的变化(字符的替换)
            /// </summary>
            /// <param name="dic">参加交叉的两个个体</param>
            /// <param name="geti1">个体1</param>
            /// <param name="geti2">个体2</param>
            /// <returns></returns>
            static List<string> Crossover_Replace(Dictionary<int, int> dic, string geti1, string geti2)
            {
                int index; double p;
                List<string> tmp_group = new List<string>();//存放交叉过后的个体
                foreach (var item in dic)
                {
                    p = rd.NextDouble();
                    if (p <= crossover_probability)//概率小于0.7进行交叉
                    {
                        index = rd.Next(0, 8);
                        geti1 = group[item.Key];//要交叉的两个个体
                        geti2 = group[item.Value];
                        //交叉的实现
                        tmp_group.Add(geti1.Insert(geti1.Length, geti2.Substring(index)).Remove(index, str_length - index));
                        tmp_group.Add(geti2.Insert(geti2.Length, geti1.Substring(index)).Remove(index, str_length - index));
                    }
                    else
                    {
                        tmp_group.Add(group[item.Key]);
                        tmp_group.Add(group[item.Value]);
                    }
                }
                return tmp_group;
            }
    View Code

    5、变异算子

    变换染色体基因的值,即0-1,1-0的变换。

            /// <summary>
            /// 变异过程个体的变化(0->1,1->0)
            /// 思路:1.将个体的编码转化成字符;2.为每个字符产生一个0~1的随机数,判断是否要进行变异操作
            /// 3.要变异则将0->1,1->0
            /// </summary>
            /// <param name="str">个体(二进制编码)</param>
            /// <param name="result">变异后的结果</param>
            /// <param name="probability">变异概率</param>
            /// <returns></returns>
            static string Mutation_Replace(string str, string result, double probability)
            {
                char[] chrArray = str.ToCharArray();
                for (int i = 0; i < chrArray.Count(); i++)
                {
                    //小于概率,替换字符
                    if (rd.NextDouble() <= probability)
                    {
                        if (chrArray[i] == '0')
                        {
                            chrArray[i] = '1';
                        }
                        else if (chrArray[i] == '1')
                        {
                            chrArray[i] = '0';
                        }
                    }
                }
                //将字符拼接成字符串
                foreach (char ch in chrArray)
                {
                    result += ch;
                }
                return result;
            }
    View Code

    其中的方法,实现不唯一,时间比较敢,也没有作一定的优化,只是为了熟悉算法而写的。

    希望能帮到初学者,也欢迎各位提出修改意见。

    完整代码可在这下载

     https://github.com/hwqdt/Catcher.Equation 

  • 相关阅读:
    实现UILabel渐变色效果
    设计模式-原型模式
    计算一/二元一次方程的类(用于动画控制)
    【转】VMware网络连接模式—桥接、NAT以及仅主机模式的详细介绍和区别
    【转】VMware虚拟机系统无法上网怎么办?
    【转】Android tools:context
    【转】android布局--Android fill_parent、wrap_content和match_parent的区别
    【转】在程序中设置android:gravity 和 android:layout_Gravity属性
    【转】android gravity属性 和 weight属性
    【转】Android xml资源文件中@、@android:type、@*、?、@+含义和区别
  • 原文地址:https://www.cnblogs.com/catcher1994/p/4512450.html
Copyright © 2020-2023  润新知