遗传算法是一种模拟自然界物种进化的算法,通过模拟一个种群的基因在自然环境下,遵循“优胜劣汰,适者生存”的达尔文进化理论,基因不断的迭代,从而进化。
理想是这个样的,此算法用于求解最优化问题,效果应该还行,下文讲解了算法的思路和具体实现方法。
变量声明
WLOG将问题转化为:多变量最大化目标函数值。
英文名字都是我自己取得,很可能不严谨~
基因(组):(Gene & Genome)由一个(或多个)二进制串构成,二进制串的每一位代表基因所携带的信息,基因的个数可以根据题目中自变量的个数确定,记为 xi
P.S. 在实际问题中,可能有多个自变量控制一个因变量,同时可能有多个限制条件,这里将每个自变量与一个基因建立同构关系,假设实际问题中存在 n 个自变量,则以下变量都可视为 n 维向量
基因长度:(Length of Gene)每一个二进制串的位数,记为 L
种群:(Population)由基因所组成的可重集合,记为 P
种群大小:(Number of Gene)记为 N=∣P∣
基因空间:(Gene Space)由所有基因所组成的空间,记为 S,不难发现如果基因维数为 1 且 S 由所有位数为 L 的二进制串构成,则 S={0,1,2,⋯,2L−1}
实际问题空间:(Issue Space)对于实际问题中所有自变量向量所组成的空间,记为 SI
实际问题目标函数:(Issue function)目标就是寻找最优解使得该函数值最大,记为 G:SI→R,(右侧其实不一定必须是实数空间,可以是任意的有序集)
基因转换函数:(Transition function for Gene) 将基因转化为对应的实际问题中所对应的自变量向量(这是一个双射),记为 f:S→SI
适应度量化函数:(Adaptation function)用于评判一个基因在自然环境下的适应程度,F:SI→R>0,注意 F(f(x)) 一定是非负实数
适应度函数取值
F(f(x)) 函数一般有三种取法:
直接法
F(f(x))=G(f(x))
要求 G(f(x))⊂R>0
界限构造法
F(f(x))={G(f(x)),0,f(x)<c;otherwise.
对最大值有上限 c 的限制。
倒数法
F(f(x))=c−G(f(x))1andc−G(f(x))>0
根据反比例函数图像知,该取法可以使得较大的值收敛的更快。
自然选择 Choose
基因的筛选:每一代下来,基因会发生筛选,依据适应度函数的大小,越大的选取到的概率越大,进入到下一代的概率也就越大,于是可以如下定义筛选概率:
P(xi)=∑i=1NF(f(xi))F(f(xi))
选择算法:使用轮盘赌选择法(区段选择),将每一个概率视为 [0,1] 区间上的一个区段,每次在其中随机一个数字,通过数字所处的区段,判断选择的基因。(可以通过前缀和,二分实现)
一些可能能用的优化:(没试过)
稳态繁殖:用部分优质新的基因更新父基因
没有重串的稳态繁殖:在稳态繁殖的基础上,基因序列两两不同。
基因重组 Recombination
基因重组,对应的就是二进制串数据的交换,设该事件发生的概率为 R,取值一般为 0.4∼0.9,这里只给出一种交叉方法:
单点交叉:交换两个基因的二进制串的最后 m 位,这里的 m 是在 [1,L] 中随机的整数,其中 L 为二进制的位数
基因突变 Mutation
基因突变,对应的就是二进制串上某一位从1
变为0
或者从0
变为1
,设该事件发生的概率为 M,取值一般为 0.001∼0.1,突变方法:
将单个基因中第 m 位(从右向左数)对 1 异或,其中 m 为 [1,L] 中的随机整数,其中 L 为二进制的位数
初始化
所有要初始化的变量全部列出来了(并给出推荐取值):
遗传过程
-
在基因空间 S 上随机分布产生第一代种群。
-
计算适应值 F(f(x)),并给出选择概率。
-
顺次进行选择、交叉、突变三个步骤生成下一代种群,后面两个步骤要满足其发生的概率。
-
循环步骤2,步骤3,直到达到迭代次数或者达到目标解,退出循环,输出结果。
例子 - 求解函数最大值
求解函数
f(x)=xsin(10πx)+2
在 [−1,2] 上的最大值,其图像参考 GeoGebra - GA练习1。
如果精度要达到6位小数,则应该将 [−1,2] 进行 3⋅106 等分,则至少要 log2(3⋅106)=21.516531<22,则 L=22,代码中详细描述了计算的过程:
点击显/隐代码
通过这个例题,可以发现,多次重启问题是解决收敛至局部最优解的一个重要方法,而且增大种群总量也能提高达到全局最优解的概率。
例子 - TSP(旅行商问题)
经典NP问题,设地图上 N 个城市(编号从 1∼N),规划路线使得每个城市都有且仅经过一次,最后回到出发的城市,求最短路径。
在此题中,一个基因代表一种路径,那么基因就不能用二进制表示了,而是 N 进制,每个基因都是 N 的一个排列,这样就保存了一条路径上的所有信息了。
适应值函数
F(f(x))=G(f(x))1
其中 G(f(x)) 表示 f(x) 这条路径的长度,为了转化为求最大解问题,故取倒数。
交叉算法(有序交叉)
此处不能再是简单的交换,因为这样就不能保证仍然是排列了。具体方法还是随机出一段序列,两个基因中保持这一段序列保持不动,将其余部分重组(通过一个例子解释下):
突变算法(倒置变异法)
随机一段序列,将其倒置即可,比如:
操作定义完成,开始打代码~
点击显/隐代码
30个点的数据
点击显/隐数据
最佳计算效果图:
最优结果为424.78,这个GA算法最优结果为449.132,效果还行,但这个是多次计算后的最优值,应该还可以提升,小数据效果不错,但城市增加估计就很难保持精度了,于是考虑能否结合其他算法一起作用提高精度。
点击显/隐结果
MATLAB 绘图代码为
点击显/隐代码
输入数据格式为
点击显/隐数据