分类: C/C++
2017-03-30 17:00:12
遗传算法引擎――GenAlg
其中Reset()函数,init()函数和CalculateBestWorstAvTot()函数都比较简单,读者查看示例程序的代码就能明白了。而下面分别介绍init函数和Epoch函数。
类的初始化函数――init函数
init函数主要充当CGenAlg类的初始化工作,把一些成员变量都变成可供重新开始遗传算法的状态。(为什么我不在构造函数里面做这些工作呢?因为我的程序里面CGenAlg类是View类的成员变量,只会构造一次,所以需要另外的初始化函数。)下面是init函数的代码:
恩,正如我之前说的,我们这个程序不但要应付基因编码只有一个浮点数的“袋鼠跳”问题的情况,还希望以后在处理一串浮点数编码的时候也一样适用,所以从这里开始我们就把基因当成串来对待。
开创新的纪元――Epoch函数
现在万事具备了,只差把所有现成的“零件”装配起来而已。而Epoch函数就正好充当这个职能。下面是这个函数的实现:
恩,到这里“袋鼠跳”的主要代码就完成了。(其它一些代码,比如图形曲线的显示,和MFC的相关代码在这就不作介绍了,建议初学者不必理会那些代码,只要读懂算法引擎部分就可以了。)下面就只等着我们下达命令了!
让袋鼠在你的电脑里进化――程序的运行
我想没有什么别的方法比自己亲手写一个程序然后通过修改相关参数不断调试程序,更能理解并且掌握一种算法了。不知道你还记不记得你初学程序的日子,我想你上机动手写程序比坐在那里看一本厚厚的程序开发指南效率不知高上多少倍,兴趣也特命浓厚,激情也特别高涨。恩,你就是需要那样的感觉,学遗传算法也是一样 的。你需要把自己的代码运行起来,然后看看程序是否按照你所想象的去运行,如果没有,你就要思考原因,按照你的想法去改善代码,试着去弄清其中的内在联系。这是一个思维激活的过程,你大脑中的神经网络正在剧烈抖动(呵呵,或许学到后面你就知道你大脑的神经网络是如何“抖动”的。),试图去接受这新鲜而有 趣的知识。遗传算法(包括以后要学到的人工神经网络)包含大量的可控参数,比如进化代数、人口数目、选择概率、交叉概率、变异概率、变异的步长还有以后学到的很多。这些参数之间的搭配关系,不能指望别人用“灌输”的方式让你被动接受,这需要你自己在不断的尝试,不断的调整中去形成一种“感觉”的。很多时候 一个参数的量变在整个算法中会表现出质的变化。而算法的效果又能从宏观上反映参数的设置。
现在就让我们来对这个程序做简单的说明。
参数的设置:
这个程序有很多的需要预先设置好的参数,为了方便修改,我把它们都定义为全局变量,定义和初始化都放在Parameter.h的头文件里面。下面对几个主要参数的说明:
当然,一些主要的参数在程序运行后可以通过参数设置选项进行设置。(其中缓冲时间是每进化一代之后,暂停的时间,单位为毫秒)如图2-6。
运行程序:
程序运行后请选择菜单项:控制->让袋鼠们开始跳吧,开始遗传算法的过程。其中蓝色的线条是函数曲线(恩,那就是喜玛拉雅山脉。其中最高的波峰,就是珠穆朗玛峰。)绿色的点是一只只袋鼠。上方的黑色曲线图表是对每一代最优的个体的适应性评分的统计图表。下方的黑色曲线图表是对每一代所有个体的平均适应性评分的统计图表。(如果你认为它们阻碍了你的视线,你可以在参数设置里面取消掉。)如图2-7所示。另外还可以用键盘的上下左右键来控制视窗的移动,加减键控制函数曲线的放缩。
刚开始的时候,袋鼠分布得比较分散它们遍布了各个山岭,有的在高峰上,有的在深谷里。(如图2-8)
经过了几代的进化后,一些海拔高度比较低的都被我们射杀了,而海拔较高的袋鼠却不断的生儿育女。(如图2-9)
最后整个袋鼠种群就只出现在最高峰上面(最优解上)。(如图2-10)
当然,袋鼠不是每一次都能跳到珠穆朗玛峰的,如图2-11所 示。(就是说不是每次都能收敛到最优解)也许它们跳到了某一个山峰,就自大的认为它们已经“会当凌绝顶”了。(当然,事实上是因为不管它们向前还是向后跳都只能得到更小的适应度,所以不等它们跳过山谷,再跳到旁边更高的山峰,就被我们射杀了。)所以,我们为了使到袋鼠每次都尽可能的攀到珠穆朗玛峰,而不是 留恋在某一个低一些的山峰,我们有两个改进的办法,其一是初始人口数目更多一些,以使最好有一些袋鼠一开始就降落到最高峰的附近,但是这种方法对于搜索空间非常大的问题往往是无能为力的。我们常常采用的方法是使袋鼠有一定的概率跳一个很大的步长,以使袋鼠有可能跳过一个山谷到更高的山峰去。这些改进的方法 留给读者自己去实现。
另外,如果把变异的机率调得比较高,那么就会出现袋鼠跳得比较活跃的局面,但是很可能丢失了最优解;而如果变异的机率比较低的话,袋鼠跳得不太活跃,找到最优解的速度就会慢一些,这也留给读者自己去体验。
作为一个寻找大值的程序,这个的效率还 很低。我希望留给初学者更多改进的空间,大家不必受限于现有的方法,大可以发挥丰富的想象力,自己想办法去提高程序的效率,然后自己去实现它,让事实去验证你的想法是否真的能提高效率,抑或刚好相反。恩,在这个过程当中,大家不知不觉地走进了遗传算法的圣殿了,胜于一切繁复公式的摆设和教条式的讲解。
博主后记:由于原作者未知加上本人学习繁忙,所以MFC版本源码未整理,以下为自己整理实现的控制台演示版本:
最后结果是一样的,附上下载: