0、前话
一周没更新了,抱歉!!!
解决运筹优化问题,无非就是使用精确算法和启发式算法。精确算法,比如分支定界,割平面,分支定价,列生成,动态规划等等。很多求解软件就是基于精确算法开发的,比如cplex、Gurobi等等。启发式算法,我所知道的可以分为三种:进化算法,如遗传算法,禁忌搜索算法,模拟退火算法;群体算法,如蚁群算法,粒子群算法等;神经网络系列算法。。经过一年的学习,看了一些算法,也动手实现了一些算法,后面有很长空闲时间的时候我会将自己的理解写出来,以便自己忘的时候再温习,可能有很多错误,希望网友指正。下面进入正题。我文字表达能力一般,可能很多人读起来不是很清楚。我会把自己编过的一些这方面的代码放到github上。
1、背景介绍
这部分参考别人文章,文章末尾标注出处。遗传算法 ( GA , Genetic Algorithm ) ,也称进化算法 。 遗传算法是受达尔文的进化论的启发,借鉴生物进化过程而提出的一种启发式搜索算法。因此在介绍遗传算法前有必要简单的介绍生物进化知识。
作为遗传算法生物背景的介绍,下面内容了解即可:
种群(Population):生物的进化以群体的形式进行,这样的一个群体称为种群。
个体:组成种群的单个生物。
基因 ( Gene ) :一个遗传因子。
染色体 ( Chromosome ) :包含一组的基因。
生存竞争,适者生存:对环境适应度高的个体参与繁殖的机会比较多,后代就会越来越多。适应度低的个体参与繁殖的机会比较少,后代就会越来越少。
遗传与变异:新个体会遗传父母双方各一部分的基因,同时有一定的概率发生基因变异。
简单说来就是:繁殖过程,会发生基因交叉( Crossover ) ,基因突变 ( Mutation ) ,适应度( Fitness )低的个体会被逐步淘汰,而适应度高的个体会越来越多。那么经过N代的自然选择后,保存下来的个体都是适应度很高的,其中很可能包含史上产生的适应度最高的那个个体。
2、主要过程
因此,遗传算法的一般流程(通用,不同问题设计的遗传算法不同,最好看论文)包括:
(1)根据问题的形式,确定问题解的编码形式。比如经典的TSP问题,编码形式一般为城市编号的序列。
(2)构造初始解。构造初始解一般采用随机的方式,但是很多问题随机方式产生的初始解效果极差且时间很慢,因此设定一些启发式规则。
(3)计算个体的适应度。适应度是评判个体优劣的标准,我的习惯是如果问题是最小化问题,则用M-目标函数做为适应度函数。
(4) 选择。计算完个体的表现,要确定哪些个体参与进化。选择的种类也很多,我在一本书上看到很多种介绍,但原理都是一样的,都是让高适应度的个体以高概率参与到进化中。经典的选择方式是轮盘赌。
(5)交叉。交叉也有很多种形式,单点交叉,多点交叉,基于位置交叉等等。有时候为了保护个体的可行性,要进行特殊的交叉。以我在一篇SCI论文中看到的一种交叉为例子。两条父代染色体中选择其中一 条,随机选择一断点,进行交叉操作。断点右侧的 基因序列继承到子代时的顺序与另外一个父代中 相应基因序列的顺序保持一致。具体步骤如下图所 示:
屏幕快照 2017-12-01 下午10.26.06.png
这里的染色体是双行基因的形式,第一行表示任务的序号,第二行表示执行任务的车号。这种交叉方式就可以很好的保护解的可行性。
(6)变异。如果说交叉可以扩展解空间或者多样性,那么变异可能就是防止过早的收敛吧。交叉变异是最重要的两个部分。变异就是改变某些基因位置的值。
屏幕快照 2017-12-01 下午10.36.15.png
具体交叉变异的深刻认识,那下次在一些遗传算法的改进上再讨论。本次只写遗传算法的基本流程介绍。
(7)精英保留。很多遗传算法里都会加入精英保留策略。这使得好的解一定会继承到下一代,但是如果过多的将精英解继承,很容易出现早熟即过早收敛。
3、整体过程
最经典的遗传算法框架都是,选择完,以一定的交叉概率判断是否发生交叉操作。然后再以一定的概率判断交叉后的个体是否发生变异。即先交叉后变异。但是很多文章中以一种奇特的方式并行进化,即交叉变异保留精英同时进行,选择完后,确定哪些个体保留精英直接继承到下一代,哪些个体发生交叉操作,哪些个体发生变异操作,这种方式的效果对于某些问题效果很好。
还有很多遗传算法的改进,比如动态调整交叉变异概率,动态调整交叉变异顺序,以及双种群遗传算法,引入竞争机制,遗传与其他算法的融合等等,还有很多中文文章号称可以避免早熟提出很多名字很响亮的算法,我是表示怀疑的。不过多评判。后续会对一些遗传算法的改进进行总结说明,也会把自己的code放到Github上。
遗传算法是最流行的算法,因为其容易上手,效果较好,但是想对其进行改进却是很难的。
注:文章开头的背景介绍参考的一篇叫做白话讲解遗传算法的博主文章。其余均是自己的小论文和参考一些英文文章中的内容。
网友评论