昨天讲了一下关于距离的计算,没有看昨天或者以前的文章,点一下历史消息或者这里:html
遗传算法可视化项目(3):建立图的数据结构
github
今天首先介绍遗传算法(genetic algorithm,GA)。数组
遗传算法是一种进化算法,其基本原理是模仿天然界中的生物“物竞天择,适者生存”的进化法则,把问题参数编码为染色体,再利用迭代的方式进行选择、交叉、变异等运算法则来交换种群中染色体的信息,最终生成符合优化目标的染色体。微信
在遗传算法中,染色体对应的是数据或者数组,一般是由一维的串结构数据来表示,串上各个位置对应基因的的取值。基因组成的串就是染色体,或者称为基因型个体。必定数量的个体组成了种群,种群中个体数目的大小称为种群大小,也称为种群规模,而各个个体对环境的适应程度称为适应度。数据结构
标准遗传算法的步骤以下:机器学习
(1)编码:遗传算法在搜索解空间以前须要将解数据表示成遗传空间的基因型串结构数据,这些串结构数据的不一样组合构成了不一样的染色体。函数
(2)初始化:即生成初始种群。具体的作法是随机生成N个初始的染色体(解空间的解),每个染色体其实就至关于一个个体,N个个体构成了一个初始种群。遗传算法以这N个个体做为初始值开始进化。
(3)适应度评估:适应度代表个体或者解的优劣性。不一样的问题,定义适应度函数的方式也不一样。好比若是是求一个函数的最大值,那么通常某个解对应的函数值越大,那么这个个体(解)的适应度也就越高。
(4)选择:选择的目的是为了从当前种群中选出优良的个体,使它们有机会成为父代繁殖下一代子孙。遗传算法经过选择过程体现这一思想,进行选择的原则是适应性强的个体为下一代贡献一个或者多个后代的几率大。这体现了达尔文的适者生存原则。
(5)交叉:交叉操做是遗传算法中最主要的遗传操做。经过交叉能够获得新一代个体,新个体组合了其父代的个体特征。交叉体现了信息交换的思想。
(6)变异:变异首先在群体中随机选择一个个体,对于选中的个体以必定的几率(一般是比较小的几率,这与天然界一致,天然界的变异都是小几率事件)随机改变染色体中某个基因的值。
有的时候除了选择选择、交叉、变异这三种操做以外,咱们还会针对具体的问题加入其它的操做(好比逆转之类),可是选择、交叉、变异是全部的遗传算法都共同的拥有的遗传操做。
其次介绍一下TSP问题。TSP(traveling salesman problem,旅行商问题)是典型的NP彻底问题,即其最坏状况下的时间复杂度随着问题规模的增大按指数方式增加,到目前为止尚未找到一个多项式时间的有效算法。TSP问题能够描述为:已知n个城市之间的相互距离,某一旅行商从某一个城市出发,访问每一个城市一次且仅一次,最后回到出发的城市,如何安排才能使其所走的路线最短。换言之,就是寻找一条遍历n个城市的路径,或者说搜索天然子集X={1,2,...,n}(X的元素表示对n个城市的编号)的一个排列P(X)={V1,V2,....,Vn},使得Td=∑d(Vi,Vi+1)+d(Vn,V1)取最小值,其中d(Vi,Vi+1)表示城市Vi到Vi+1的距离。TSP问题不只仅是旅行商问题,其余许多NP彻底问题也能够归结为TSP问题,如邮路问题,装配线上的螺母问题和产品的生产安排问题等等,也使得TSP问题的求解具备更加普遍的实际意义。
再来讲针对TSP问题使用遗传算法的步骤。
(1)编码问题:因为这是一个离散型的问题,咱们采用整数编码的方式,用1~n来表示n个城市,1~n的任意一个排列就构成了问题的一个解。能够知道,对于n个城市的TSP问题,一共有n!种不一样的路线。
(2)种群初始化:对于N个个体的种群,随机给出N个问题的解(至关因而染色体)做为初始种群。这里具体采用的方法是:1,2,...,n做为第一个个体,而后2,3,...,n分别与1交换位置获得n-1个解,从2开始,3,4,...,n分别与2交换位置获得n-2个解,依次类推。(若是这样还不够初始种群的数量,能够再考虑n,n-1,...,1这个序列,而后再按照相同的方法生成等等)
(3)适应度函数:设一个解遍历初始行走的总距离为D,则适应度fitness=1/D,即总距离越高,适应度越低,总距离越低(解越好),适应度越高。
(4)选择操做:个体被选中的几率与适应度成正比,适应度越高,个体被选中的几率越大。这里仍然采用轮盘赌法。
(5)交叉操做:交叉操做是遗传算法最重要的操做,是产生新个体的主要来源,直接关系到算法的全局寻优能力,这里采用部分映射交叉。好比对于n=10的状况,对于两个路径:
1 2 4 5 6 3 9 10 8 7
3 9 7 6 8 10 5 1 2 4
随机产生两个[1,10]之间的随机数r1,r2,表明选择交叉的位置,好比r1=2,r2=4,将第一个个体r1到r2之间的基因(即城市序号)与第二个个体r1到r2之间的基因交换,交换以后变为:
1 9 7 6 6 3 9 10 8 7
3 2 4 5 8 10 5 1 2 4
这个时候会发现可能交叉过来的基因与原来其余位置上的基因有重复,容易直到,第一个个体重复基因的数目与第二个个体重复基因的数目是相同的(这里都是3个),只须要把第一个个体重复的基因与第二个个体重复的基因作交换,便可以消除冲突。消除冲突以后的解以下:
1 9 7 6 5 3 2 10 8 4
3 2 4 5 8 10 6 1 9 7
(6)变异操做:变异操做采起对于一个染色体(即个体)随机选取两个基因进行交换的策略。好比对于染色体:
2 4 6 10 3 1 9 7 8 5
随机选取了两个位置p1=3,p2=8,交换这两个位置的基因,获得新的染色体为:
2 4 7 10 3 1 9 6 8 5
(7)进化逆转操做:这个是标准的遗传算法没有的,是咱们为了加速进化而加入的一个操做。这里的进化是指逆转操做具备单向性,即只有逆转以后个体变得更优才会执行逆转操做,不然逆转无效。具体的方法是,随机产生[1,10](这里仍然以10个城市为例)之间的两个随机数r1和r2(其实也是容许相同的,只是r1,r2相同以后,逆转天然无效,设置交叉变异都是无效的,可是这不会常常发生),而后将r1和r2之间的基因进行反向排序。好比对于染色体:
1 3 4 2 10 9 8 7 6 5
r1=3,r2=5,它们之间的基因反向排列以后获得的染色体以下:
1 3 10 2 4 9 8 7 6 5
说了这么多,接下来就是代码实现了,仍是打开以前VS2017建立的项目:在解决方案资源管理器右击头文件→添加→新建项,而后在弹出的窗口点击头文件,取个名字(我这里就叫GA.h了),最后肯定就行,首先是包含头文件,宏定义(最大进化代数,种群数目,交叉几率,变异几率大佬能够随便改,但小白菜鸟建议仍是用我给的数),定义全局变量和函数声明,代码以下:
接下来就是每个函数的实现,首先是init函数,实现代码以下:
而后是距离函数和最小值函数,代码以下:
接着是路径总长度函数,代码以下:
目前为止,进入选择,交叉,变异三大基本操做的实现了,首先是选择操做,代码以下:
而后就是最复杂的代码最多(多到我连图都不能一次截完)的交叉操做,代码以下:
而后是变异操做,代码以下:
目前为止三大基本操做结束了,还差一个逆转操做,逆转操做代码以下:
最后还差一步计算并把结果传给昨天建立的图,代码以下:
遗传算法目前为止理论和C语言实现讲完了,今天的文章也就到此结束,文章最后附上项目地址:https://github.com/3480430977/DataVisualizationOfGA
最后欢迎你们扫码关注
本文分享自微信公众号 - Python机器学习算法说书人(Python-ML-Algorithm)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。