遗传算法(Genetic Algorithm)是模拟自然界生物进化机制的一种算法即遵循适者生存、优胜劣汰的法则也就是寻优过程中有用的保留无用的则去除. 在科学和生产实践中表现为在所有可能的解决方法中找出最符合该问题所要求的条件的解决方法即找出一个最优解. 这种算法是1960年由Holland提出来的其最初的目的是研究自然系统的自适应行为并设计具有自适应功能的软件系统. 它的特点是对参数进行编码运算不需要有关体系的任何先验知识沿多种路线进行平行搜索不会落入局部较优的陷阱,能在许多局部较优中找到全局最优点是一种全局最优化方法[1-3]. 近年来,遗传算法已经在国际上许多领域得到了应用. 该文将从遗传算法的理论和技术两方面概述目前的研究现状描述遗传算法的主要特点、基本原理以及改进算法,介绍遗传算法的应用领域,并用MATLAB实现了遗传算法及最优解的求解.
科学研究、工程实际与国民经济发展中的众多问题可归结作“极大化效益、极小化代价”这类典型模型. 求解这类模型导致寻求某个目标函数(有解析表达式或无解析表达式)在特定区域上的最优解. 而为解决最优化问题目标函数和约束条件种类繁多,有的是线性的,有的是非线性的;有的是连续的,有的是离散的;有的是单峰值的,有的是多峰值的. 随着研究的深入,人们逐渐认识到:在很多复杂情况下要想完全精确地求出其最优解既不可能,也不现实,因而求出近似最优解或满意解是人们的主要着眼点之一. 总的来说,求最优解或近似最优解的方法有三种: 枚举法、启发式算法和搜索算法.
(1)枚举法. 枚举出可行解集合内的所有可行解以求出精确最优解. 对于连续函数,该方法要求先对其进行离散化处理,这样就有可能产生离散误差而永远达不到最优解. 另外,当枚举空间比较大时该方法的求解效率比较低,有时甚至在目前最先进的计算工具上都无法求解.
(2)启发式算法. 寻求一种能产生可行解的启发式规则以找到一个最优解或近似最优解. 该方法的求解效率虽然比较高,但对每一个需要求解的问题都必须找出其特有的启发式规则,这个启发式规则无通用性不适合于其它问题.
(3)搜索算法. 寻求一种搜索算法,该算法在可行解集合的一个子集内进行搜索操作以找到问题的最优解或近似最优解. 该方法虽然保证了一定能够得到问题的最优解,但若适当地利用一些启发知识就可在近似解的质量和求解效率上达到一种较好的平衡.
随着问题种类的不同以及问题规模的扩大,要寻求一种能以有限的代价来解决上述最优化问题的通用方法仍是一个难题. 而遗传算法却为我们解决这类问题提供了一个有效的途径和通用框架开创了一种新的全局优化搜索算法.
50年代末到60年代初,自然界生物进化的理论被广泛接受生物学家Fraser,试图通过计算的方法来模拟生物界“遗传与选择”的进化过程,这是遗传算法的最早雏形. 受一些生物学家用计算机对生物系统进行模拟的启发,Holland开始应用模拟遗传算子研究适应性. 在1967年,Bagley关于自适应下棋程序的论文中,他应用遗传算法搜索下棋游戏评价函数的参数集并首次提出了遗传算法这一术语. 1975年,Holland出版了遗传算法历史上的经典著作《自然和人工系统中的适应性》,首次明确提出遗传算法的概念. 该著作中系统阐述了遗传算法的基本理论和方法,并提出了模式(schemat atheorem)[4],证明在遗传算子选择、交叉和变异的作用下具有低阶、短定义距以及平均适应度高于群体平均适应度的模式在子代中将以指数级增长. Holand创建的遗传算法,是基于二进制表达的概率搜索方法. 在种群中通过信息交换重新组合新串;根据评价条件概率选择适应性好的串进入下一代;经过多代进化种群最后稳定在适应性好的串上. Holand最初提出的遗传算法被认为是简单遗传算法的基础,也称为标准遗传算法.
(1)20世纪60年代,John Holland教授和他的数位博士受到生物模拟技术的启发,认识到自然遗传可以转化为人工遗传算法. 1962年,John Holland提出了利用群体进化模拟适应性系统的思想,引进了群体、适应值、选择、变异、交叉等基本概念.
(2)1967年,J.D.Bagely在其博士论文中首次提出了“遗传算法”的概念.
(3)1975年,Holland出版了《自然与人工系统中的适应性行为》(Adaptation in Natural and Artificial System).该书系统地阐述了遗传算法的基本理论和方法,提出了遗传算法的基本定理—模式定理,从而奠定了遗传算法的理论基础. 同年De Jong在其博士论文中,首次把遗传算法应用于函数优化问题对遗传算法的机理与参数进行了较为系统地研究并建立了著名的五函数测试平台.
(4)20世纪80年代初,Holland教授实现了第一个基于遗传算法的机器学习系统—分类器系统(Classifier System简称CS),开创了基于遗传算法的机器学习的新概念.
(5)1989年,David Goldberg出版了《搜索、优化和机器学习中的遗传算法》(Genetic Algorithms in Search Optimization and Machine Learning).该书全面系统地总结了当时关于遗传算法的研究成果,结合大量的实例完整的论述了遗传算法的基本原理及应用,奠定了现代遗传算法的基础.
(6)1992年,John R.Koza出版了专著《遗传编程》(Genetic Programming)提出了遗传编程的概念,并成功地把遗传编程的方法应用于人工智能、机器学习、符号处理等方面. 随着遗传算法的不断深入和发展,关于遗传算法的国际学术活动越来越多,遗传算法已成为一个多学科、多领域的重要研究方向.
今天遗传算法的研究已经成为国际学术界跨学科的热门话题之一. 遗传算法是一种有广泛应用前景的算法,但是它的研究和应用在国内尚处于起步阶段. 近年来遗传算法已被成功地应用于工业、经济管理、交通运输、工业设计等不同领域解决了许多问题.例如可靠性优化、流水车间调度、作业车间调度、机器调度、设备布局设计、图像处理以及数据挖掘等.
随机初始化种群p(0)={x1,x2,...,xn};t=0;计算p(0)中个体的适应值;
while(不满足终止条件)
{ 根据个体的适应值及选择策略从p(t)中选择下一代生成的父体p(t);
执行交叉,变异和再生成新的种群p(t+1) ;
计算p(t+1)中个体的适应值;
t=t+1;
}
伪代码为:
BEGIN:
I=0;
Initialize P(I);
Fitness P(I);
While (not Terminate2Condition)
{
I++;
GA2Operation P(I);
Fitness P(I);
}
END.
(1)编码表示
Holland在运用模式定理分析编码机制时,建议使用二进制编码,但二进制编码不能直接反映问题的固有结构精度不高,个体长度大,占用计算机内存多.解决这个问题的措施有:
①动态编码(dynamic encoding)GA是当算法收敛到某局部最优时增加搜索的精度从而使得在全局最优点附近,可以进行更精确的搜索,增加精度的办法是在保持串长不变的前提下减小搜索区域.
②对于问题的变量是实向量的情形,可以直接采用实数进行编码,这样可以直接在解的表现型上进行遗传操作,从而便于引入与问题领域相关的启发式信息以增加算法的搜索能力.
③复数编码的GA是为了描述和解决二维问题,基因用x+yi表示,其还可以推广到多维问题的描述中.
④多维实数编码GA使无效交叉发生的可能性大大降低,同时其合理的编码长度也有助于算法在短时间内获得高精度的全局最优解.
⑤ 在组合优化中,可以使用有序串编码. 当问题的表示是树和图时,我们还可以使用结构式编码.
(2)适应度函数
适应度函数是用来区分群体中个体好坏的标准,是自然选择的唯一标准,选择的好坏直接影响算法的优劣. 选择的不容易引起两种不利于优化的现象:
①异常个体引起早熟收敛,影响求得全局最优解. 这种现象常出现在小规模群体中. 在遗传进化的早期,一些超常个体的适应度很大,在群体中占有很大的比例,这些异常个体因竞争力太突出而控制了选择过程,结果使得算法过早收敛.
②个体差距不大,引起搜索成为随机漫游. 当群体中个体的适应度差别不大,个体间竞争力减弱,特别是平均适应度以接近最佳适应度时,最佳个体与其他许多个体在选择过程中就会有大体相等的选择机会,从而使有目标的优化搜索过程变成无目标的随机漫游,影响求得全面最优解. 对于上述问题可以通过引入适应度函数定标技术来加快收敛速度和跳出局部最优点. 针对第一种情况,我们可以通过缩小相应的适应度函数值降低超常个体的竞争力;对于第二种情况,我们可以放大相应的适应度函数值以拉开个体之间的差距,提高个体间的竞争力.对适应值进行定标就是通过变换改变原适应值间的比例关系,常用的比例变换有线性变换、乘幂变换和指数变换等.
(3)选择策略
优胜劣汰的选择机制使得适应值大的个体有较大的存活机会,不同的选择策略对算法性能有较大的影响. 轮盘赌法是使用最多的选择策略,但这种策略可能会产生较大的抽样误差,于是对此提出了很多的改进方法,如繁殖池选择、Boltzmann选择、非线性排名选择、基于局部竞争机制的选择如(λ+μ)选择等等.
(4)控制参数
控制参数一般有群体大小、交换概率、变异概率等,这些参数对遗传算法性能影响较大. 在标准的遗传算法中采用经验进行估计,这将带来很大的盲目性而影响算法的全局最优性和收敛性,人们意识到这些参数应该随着遗传进化而自适应变化. 基于这一观,Davis提出自适应算子概率方法,即用自适应机制把算子概率与算子产生的个体适应性结合,高适应性值被分配高算子概率. 这种方法较好地解决了这一问题.
遗传算法提供了一种求解复杂系统优化问题的通用框架,它不依赖于问题的具体领域,对问题的种类有很强的鲁棒性即健壮性,所以广泛应用于很多学科.下是遗传算法的一些主要应用领域:
(1)函数优化.函数优化是遗传算法的经典应用领域,也是对遗传算法进行性能评价的常用算例.[18] 很多人构造出了各种各样的复杂形式的测试函数,有连续函数好有离散函数,有凸函数也有凹函数,人们用这些几何特性各异的函数来评价遗传算法的性能. 而对于一些非线性、多模型、多目标的函数优化问题,用其他优化方法较难求解,遗传算法却可以方便地得到较好的结果.
(2)组合优化. 随着问题规模的扩大,组合优化问题的搜索空间急剧扩大,有时在目前的计算机上用枚举法很难或者甚至不可能得到其精确最优解. 对于这类复杂问题,人们已意识到应把精力放在寻求其满意解上,而遗传算法则是寻求这种满意解的最佳工具之一. 实践证明,遗传算法对于组合优化中的NP完全问题非常有效.,例如,遗传算法已经在求解旅行商问题、背包问题、装箱问题、图形划分问题等方面得到成功的应用.
(3)生产调度问题. 生产调度问题在许多情况下所建立起来的数学模型难以精确求解,即使经过一些简化之后可以进行求解,也会因简化太多而使得求解结果与实际甚远. 因此,目前在现实生产中好主要靠一些经验进行调度. 遗传算法已成为解决复杂高度问题的有效工具,在单件生产车间调度、流水线生产车间调度、生产规划、任务分配等方面遗传算法都得到了有效的应用.
(4)自动控制. 在自动控制领域中许多与优化相关的问题需要求解,遗传算法的应用日益显示了良好的效果. 例如用遗传算法进行航空控制系统的优化、基于遗传算法的模糊控制器优化设计、基于遗传算法的参数辨识、利用遗传算法进行人工神经网络的结构优化设计和权值学习都显示出了遗传算法在这些领域中应用的可能性.
(5)机器人智能控制. 机器人是一类复杂的难以精确建模的人工系统,而遗传算法的起源就来自于对人工自适应系统的研究,所以机器人智能控制理所当然地成为遗传算法的一个重要应用领域. 例如遗传算法已经在移动机器人路径规划、关节机器人运动轨迹规划、机器人逆运动学求解、细胞机器人的结构优化和行动协调等方面得到研究和应用.
(6)图像处理和模式识别. 图像处理和模式识别是计算机视觉中的一个重要研究领域. 在图像处理过程中,如扫描、特征提取、图像分割等不可避免地会产生一些误差这些误差会影响到像处理和识别的效果. 如何使这些误差最小是使视觉达到实用化的重要要求. 遗传算法在图像处理中的优化计算方面是完全胜任的. 目前已在图像恢复、图像边缘特征提取、几何形状识别等方面得到了应用.
(7)人工生命. 人工生命是用计算机等人工媒体模拟或构造出具有自然生物系统特有行为的人造系统. 自组织能力和自学习能力是人工生命的两大主要特征. 人工生命与遗传算法有着密切的关系,基于遗传算法的进化模型是研究人工生命现象的重要理论基础. 虽然人工生命的研究尚处于启蒙阶段,但遗传算法已在其进化模型、学习模型、行为模型等方面显示了初步的应用能力. 可以预见,遗传算法在人工生命及复杂自适应系统的模拟与设计、复杂系统突现性理论研究中,将得到更为深入的发展.
(8)遗传程序设计. 1989年,美国Standford大学的Koza教授发展了遗传编程的概念,其基本思想是:采用树型结构表示计算机程序,运用遗传算法的思想,通过自动生成计算机程序来解决问题. 虽然遗传编程的理论尚未成熟,应用也有一些限制,但它已成功地应用于人工智能、机器学习等领域,目前公开的遗传编程实验系统有十多个,例如,Koza开发的ADF系统,White开发的GPELST系统等.
(9)机器学习. 学习能力是高级自适应系统所应具备的能力之一. 基于遗传算法的机器学习,特别是分类器系统,在许多领域得到了应用. 例基于遗传算法的机器学习可用于调整人工神经网络的连接权,也可用于神经网络结构的优化设计.
(10)数据挖掘. 数据挖掘是近几年出现的数据库技术,它能够从大型数据库中提取隐含的、先前未知的、有潜在应用价值的知识和规则. 许多数据挖掘问题可看成是搜索问题,数据库看作是搜索空间,挖掘算法看作是搜索策略. 因此,应用遗传算法在数据库中进行搜索,对随机产生的一组规则进行进化,直到数据库能被该组规则覆盖,从而挖掘出隐含在数据库中的规则. Sunil已成功地开发了一个基于遗传算法的数据挖掘工具,利用该工具对两个飞机失事的真实数据库进行了数据挖掘实验,结果表明遗传算法是进行数据挖掘的有效方法之一.
Matlab是一个高性能的计算软件,配备有功能强大的数学函数支持库,适用范围大,编程效率高,语句简单,功能齐备,是世界上顶级的计算与仿真程序软件. 利用Matlab来编写遗传算法程序简单而且易于操作.
(1)编码
编码就是把一个问题的可行解从其解空间转换到遗传算法能够处理的搜索空间的转化方法,编码形式决定了重组算子的操作. 遗传算法是对编码后的个体作选择与交叉运算,然后通过这些反复运算达到优化目标. 遗传算法首要的问题是通过编码将决策变量表示成串结构数据. 我们常用的是二进制编码,即用二进制数构成的符号串来表示每个个体. 通常根据搜索精度(sca_var)、决策变量上界(range(2)) 的和下界(range(1))来确定各个二进制字符串的长度(bit_n),搜索精度为sca_var=(range(2)-range(1))./(2^bit_n—1),然后再随机产生一个的初始种群(be_gen),其规模为popusize. 下面用encoding函数来实现编码和产生初始的种群:
function [be_gen,bit_n]=encoding(sca_var,range(1),range(2),popusize)
bit_n=ceil(log2 (( range(2)- range(1))./sca_var));
be_gen= randint( popusize, sum(bit_n));
(2)译码
决策变量经过编码之后,各个个体构成的种群be_gen 要通过解码才能转换成原问题空间的决策变量构成的种群vgen,这样才能计算其相应的各个适应度值.另外,译码首先要求出二进制数对应的十进制数decimal,然后根据下面的公式求出实际决策变量X: X=range(1)+decimal*sca_dec. 通常可以用decoding函数[19]来实现译码的过程:
function[vgen,fitness]=decoding(fcn,be_gen,bit_n,range(1),range(2))
popusize=size(be_gen,1);
n_var=length(bit_n);
sca_dec=(range(2)- range(1))./(2^bit_n- 1);
bit_n=cumsun(bit_n);
bit_n=[0 bit_n];
for i=1:n_var
be_var(i)=be_gen(:,bits(i)+1:bit_n(i+1));
var(i)= range(1)(i)+sum(ones(popusize,1)*2.^(size(be_var(i),2)- 1:- 1:0).*be_var(i),2).*sca_dec(i);
end
vgen=[var(1,:)];
for i=1:popusize
fitness(i)=eval([fcn,’(var_gene(i,:))’] );
end
(3)选择
选择就是利用码后求得的各个个体的适应度的大小,从中选出一些适应度高的个体,并淘汰一些适应度较小的个体以生成交配池的过程. 然后再对优良的个体进行交叉和变异操作. 在选择算子中,先找出当前群体中适应度最高和最低的个体,将最佳个体bes_ind 保留并替换最差个体,直接进入下一代,将剩余个体evol_gen 按适应值比例选择法进行操作,即采用轮盘赌(roulettewheel)方式来实现. 这种方式首先计算每个个体的适应值,然后计算出该适应值在群体适应值总和中所占的比例,来表示该个体被选中的概率,这样既能保证最佳个体的适应度值不会减小,最佳个体不会被交叉变异操作所破坏,也能不断提高该群体的平均适应度值. 比例选择法体现了生物进化过程中“优胜劣汰,适者生存” 的思想,并且保证将优良的基因遗传给下一代. 我们可以用下面的函数来实现选择算子:
function [evol_gen,bes_ind,max_fitness]=selection(old_gen,fitness)
[min_fitn,expo(b)]=min(fitn); [max_fitn,expo(a)]=max_(fitn);
popusize=length(fitness);
bes_ind=old_gen(expo(a),:);
expo=[1:popusize];expo(expo(a))=0;expo(expo(b))=0;
expo=nonzeros(expo);
evol_gen=old_gen(expo,:);
evol_fitness=fitness(expo,:);
evol_popusize=popusize-2;
posel=evol_fitness/sum(evol_fitness);
poselcum=cusum(posel);
r=rand(1,evol_popusize);
selected=1+sum(poselcum*ones(1,evol_popusize) evol_gen=evol_gen(selection,:); (4)重组 重组算子是产生新个体的主要方法,它决定了遗传算法的全局搜索能力. 重组操作的作用是将原有的优良基因遗传给下一代个体. 并生成包含更优良基因的新个体. 通常使用的遗传算子是一点交叉法,就是按交叉概率pc(0 function [new_gen]=recombination(old_gen,pc) [nouse,match]=sort(rand(size(old_gen,1),1)); match_gen=old_gen(match,:); pairs=size(match- gen,1)/2; bit_n=size(match_gene,2); string=rand(pairs,1) crossp=randint(string,1,[1,bit_n]); crossp=string.*crossp; for i=1:pairs new_gen([2*i-1 2*i],:)=[match_gen([2*i-1 2*i],1:crossp(i)) match_gen([2*i 2*i-1],crossp(i)+1:bin_n)]; end 另外,一点交叉法操作的信息比较小,交叉点的位置的选择可能会带来较大的偏差,一点交叉算子不利于长距离的保留和重组. (5)变异 变异算子是模拟自然界生物进化的中染色体的基因突变现象,从而改变染色体的结构和物理性状. 变异算子是产生新个体的辅助方法,它决定了遗传算法的局部搜索能力.变异操作通过按照变异概率(mp)随机反转某位等位基因的二进制字符的值来实现. 程序如下: function [new_gen]=mutation(old_gen,pm) mpoints=find(rand(size(old_gen)) new_gen=old_gen; new_gen(mpoints)=1- old_gen(mpoints); end 当重组操作发生早熟收敛时,这时引入变异算子会有很好的效果. 一方面,变异算子可以使群体进化中丢失的等位基因信息得以恢复,保持群体基因中的差异性,防止发生早熟收敛;另一方面,当种群规模较大时,在重组操作基础上引入适度的变异,也能够提高遗传算法的局部搜索效率.