遗传算法(Genetic Algorithm,GA)是模拟生物在自然环境中的遗传和进化的过程而形成的自适应全局优化搜索算法。其本质是一种并行、高效、全局搜索的方法,它能在搜索过程中自动获取和积累有关搜索空间的知识,并自适应地控制搜索过程以求得最优解。遗传算法的每一代中,根据个体在问题域中的适应度值和从自然遗传学中借鉴来的再造方法进行个体选择,产生一个新的近似解。这个过程导致种群中个体的进化,得到的新个体比原个体更能适应环境,就像自然界中的改造一样。
达尔文的自然选择学说表明,遗传和变异是决定生物进化的内在因素。遗传能使生物的性状不断地传送给后代,因此保持物种的特性;变异能够使生物的性状发生改变,从而适应新的环境而不断地向前发展。生物体自身通过基因的复制和交叉,使其性状的遗传得到选择和控制。同时,通过基因重组、基因变异和染色体在结构和数目上的变异产生丰富多彩的变异现象。
生物遗传和进化的规律有:
(1)生物的所有遗传信息都包含在其染色体中,染色体决定了生物的性状。染色体是由基因及其有规律的排列所构成的。
(2)生物的繁殖过程是由其基因的复制过程来完成的。同源染色体的交叉和变异会产生新的物种,使生物呈现新的性状。
(3)对环境适应能力强的基因或染色体,比适应能力差的基因或染色体有更多的机会遗传到下一代。
模式定理
模式定义:模式是描述种群中在位串的某些确定位置上具有相似性的位串子集的相似模板。
如二值字符集{0,1},由此可以产生通常的0、1字符串。增加一个符号*,称为“通配符”,既可以当做0也可以当做1。这样,二值字符串{0,1}就拓展为三数值字符集{0,1,*},由此可以产生诸如0110,0*11**,**01*10之类的字符串。基于三值字符集{0,1,*}所产生的能描述具有某些结构相似性的0、1字符串集的字符串,称作模式。这里需要强调的是,*只是一个描述符,而非遗传算法中实际的运算符号,它仅仅是为了描述上的方便而引入的符号而已。
模式的概念可以简明地描述具有相似结构特点的个体编码字符串。在引入了模式概念之后,遗传算法的本质是对模式所进行的一系列运算,即通过选择操作数将当前群体中的优良模式遗传到下一代群体中,通过交叉操作数进行模式的重组,通过变异操作数进行模式的突变。通过这些遗传运算,一些较差的模式逐步被淘汰,而一些较好的模式逐步被遗传和进化,最终就可以得到问题的最优解。
多个串中隐含着多个不同的模式。确切地说,长度为L的串,隐含着个不同的模式,而不同的模式所匹配的串的个数是不同的。为了反映这种确定性的差异,引入模式阶概念。
模式阶定义:模式H中确定位置的个数称作该模式的模式阶,记O(H)。例如,模式011*1*的阶数为4,模式0*****的阶数为1。显然一个模式的阶数越高,其样本数就越少,因为确定性就越高。但是,模式阶并不能反映模式的所有性质;即使具有同阶的模式,在遗传操作下,也会有不同的性质。为此,引入定义距概念。
定义距定义:在模式H中第一个确定位置和最后一个确定位置之间的距离称作该模式的定义距,记作D(H)。
模式定理:在遗传算法选择、交叉和变异算子的作用下,具有低阶、短定义距,并且其平均适应性高于群体平均适应度的模式在子代中将呈指数级增长。模式定理又称为遗传算法的基本定理。模式定理阐述了遗传算法的理论基础,说明了模式的增加规律。模式定理说明了具有某种结构特征的模式在遗传进化过程中其样本数目将呈现指数级增长。
积木块假设
积木块定义:具有低阶、短定义距以及高平均适应度的模式称作积木块。
模式定理说明积木块的样本呈现指数级增长,亦即说明了用遗传算法寻求最优样本的可能性,但它并未指明遗传算法一定能寻求到最优样本;而积木块假设却说明了遗传算法的这种能力。
积木块假设:个体的积木块通过选择、交叉、变异等遗传算子的作用,能够互相结合在一起,形成高阶、长距、高平均适应度的个体编码串。
积木块假设说明了用遗传算法求解各类问题的基本思想,即通过基因块之间的互相拼接能够产生出问题的更好的解,最终生成全局最优解。
总结:从遗传算法的模式定理得到:具有高适应度、低阶、短定义距的模式的数量会在种群的进化中呈现指数级增长,从而保证了算法获得最优解的一个必要条件。而另一方面,积木块假设则指出:遗传算法有能力使优秀的模式向着更优的方向进行,即遗传算法有能力搜索到全局最优解。
遗传学与遗传算法术语对应关系如下表:
表1:遗传学与遗传算法术语对应关系
群体:生物进化过程中的一个集团,表示可行解集。
个体:组成群体的单个生物体,表示可行解。
染色体:包含生物体所有遗传信息的化合物,表示可行解的编码。
基因:控制生物体某种性状(即遗传信息)的基本单位,表示可行解编码的分量。
遗传编码:遗传编码将优化变量转化为基因的组合表示形式,优化变量的编码机制有二进制编码、十进制编码(实数编码)等。
二进制编码:例如,求实数区间【0.4】上函数f(x)的最大值,传统的方法是不断调整自变量x本身的值,直到获得函数最大值;遗传算法则不对参数本身进行调整,而是首先将参数进行编码,形成位串,再对位串进行操作。在这里,假设使用二进制编码形式,我们可以由长度为6的位串表示变量x,即从000000到111111,并将中间的取值映射到实数区间【0,4】内。由于从整数上来看,6位长度的二进制编码位串可以表示0~63,所以对应【0,4】,每个相邻值之间的阶跃值为4/63=0.0635,这个就是编码精度。一般来说,编码精度越高,所得到的解的质量也越高,意味着解更为优良;但同时,由于遗传操作所需要的计算量也更大,因此算法的耗时将更长。因为在解决实际问题时,编码位数需要适当选择。
实数编码:在解决一些数值优化问题(尤其是高维、连续优化问题)时,经常采用实数编码方式。
适应度:适应度即生物群体中个体适应生存环境的能力。在遗传算法中,用来评价个体优劣的数学函数,称为个体的适应度函数。遗传算法在进化搜索中基本不用外部信息,仅以适应度函数为依据。它的目标函数不受连续可微的约束,且定义域可以为任意集合。对适应度函数的唯一要求是,针对输入可计算出能进行比较的结果。在具体应用中,适应度函数的设计要结合求解问题本身的要求而定。适应度函数评估是选择操作的依据,适应度函数设计直接影响遗传算法的性能。常见的适应度函数构造方法主要有:目标函数映射成适应度函数,基于序的适应度函数等。
遗传操作:遗传操作是优选强势个体的“选择”、个体间交换基因产生新个体的“交叉”、个体基因信息突变而产生新个体的“变异”这三种变换的统称。
(1)选择算子:根据个体的适应度,按照一定的规则或方法,从第t代群体P(t)中选择出一些优良的个体遗传到下一代群体P(t+1)中。
(2)交叉算子:将群体P(t)中选中的各个个体随机搭配,对每一对个体。以某一概率(交叉概率Pc)交换它们之间的部分染色体。通过交叉,遗传算法的搜索能力得以飞跃提高。
(3)变异算子:对群体中的没个个体,以某一概率(变异概率Pm)将某一个或某一些基因座上的基因值改变为其他的等位基因值。根据个体编码方式的不同,变异方式有:实值变异、二进制变异。对于二进制的变异,对相应的基因值取返;对于实值的变异,对相应的基因值用取值范围内的其他随机值替代。
标准遗传算法又称为经典遗传算法,它的优化变量由二进制编码来描述,多个优化变量的二进制编码串接在一起组成染色体,这种编码即适用于变异操作,又适用于交叉操作。在创建初始群体时,代表个体的二进制串是在一定字长的限制下随机产生的。交叉算子作用在按交叉概率选中的两个染色体上,随机选中交叉位置,将两个染色体上对应于这些位置上的二进制数值进行交换,生成两个新的个体;而变异算子作用在按变异概率随机选中的个体上,一般是随机选定变异位,将该位的二进制值取反,生成一个新的个体。
(1)遗传算法以决策变量的编码作用运算对象。这种对决策变量的编码处理方式,使得在优化计算过程中可以借鉴生物学中染色体和基因等概念,模仿自然界中生物的遗传和进化等的机理,方便地应用遗传操作算子。特别是对一些只有代码概念而无数值概念或很难有数值概念的优化问题,编码处理方式更显示出了其独特的优越性。
(2)遗传算法直接以目标函数作为搜索信息。它仅使用由目标函数值变换来的适应度函数值,就可确定进一步的搜索方向和搜索范围,而不需要目标函数的导数值等其他一些辅助信息。实际应用中很多函数无法或很那求导,甚至根本不存在导数,对于这类目标函数的优化和组合优化问题,遗传算法就显示了其高度的优越性,因为它避开了函数求导这个障碍。
(3)遗传算法同时使用多个搜索点的搜索信息。遗传算法对最优解的搜索过程,是从一个由很多个体所组成的初始群体开始的,而不是从单一的个体开始的。对这个群体所进行的选择、交叉、变异等运算,产生出新一代的群体,其中包括了很多群体信息。这些信息可以避免搜索一些不必搜索的点,相当于搜索了更多的点,这是遗传算法所特有的一种隐含并行性。
(4)遗传算法是一种基于概率的搜索技术。遗传算法属于自适应概率搜索技术,其选择、交叉、变异等运算都是以一种概率的方式来进行的,从而增加了其搜索过程的灵活性。虽然这种概率特性也会使群体中产生一些适应度不高的个体,但随着进化过程的进行,新的群体中总会更多地产生出优良的个体。与其他一些算法相比,遗传算法的鲁棒性使得参数对其搜索效果的影响尽可能小。
(5)遗传算法具有自组织、自适应和自学习等特性。当遗传算法利用进化过程获得信息自行组织搜索时,适应度大的个体具有较高的生存概率,并获得更适应环境的基因结构。同时,遗传算法具有可扩展性,易于同别的算法想结合,生成综合双方优势的混合算法。
标准遗传算法的主要本质特征,在于群体搜索策略和简单的遗传算子,这使得遗传算法获得强大的全局最优解搜索能力、问题域的独立性、信息处理的并行性、应用的鲁棒性和操作的简明行,从而成为一种具有良好适应性和可规模化的求解方法。但大量的实践和研究表明,标准遗传算法存在局部搜索能力差和“早熟”等缺陷,不能保证算法收敛。
在现有的许多文献中出现了针对标准遗传算法的各种改进算法,并取得了一定的成效。它们主要集中在对遗传算法的性能有重大影响的6个方面:编码机制、选择策略、交叉算子、变异算子、特殊算子、和参数设计(包括群体规模、交叉概率、变异概率)等。
此外,遗传算法与差分进化算法、免疫算法、蚁群算法、粒子群算法、模拟退火算法、禁忌搜索算法和量子计算等结合起来所构成的各种混合遗传算法,可以综合遗传算法和其他算法的优点,提高运行效率和求解质量。
遗传算法使用群体搜索技术,通过对当前群体施加选择、交叉、变异等一系列遗传操作,从而产生出新一代的群体,并逐步使群体进化到包含或接近最优解的状态。
在遗传算法中,将n维决策向量用n个记号Xi(i=1,2,3……,n)所组成的符号串X来表示:
把每一个Xi看做一个遗传基因,它的所有可能取值就称为等位基因,这样,X就可看作由n个遗传基因所组成的一个染色体。一般情况下,染色体的长度是固定的,但对一些问题来说它也可以使变化的。根据不同的情况,这里的等位基因可以是一组整数,也可以是某一范围内的实数,或者是一个存粹的记号。最简单的等位基因是由0或1的符号串组成的,相应的染色体就可以表示为一个二进制符号串。这种编码所形成的的排列形式是个体的基因型,与它对应的X值是个体的表现型。染色体X也称为个体X,对于每一个个体X,要按照一定的规则确定其适应度。个体的适应度与其对应的个体表现型X的目标函数值相关联,X越接近目标函数的最优点,其适应度越大;反之,适应度越小。
遗传算法的流程具体步骤如下:
(1)初始化。设置进化代数计数器g=0,设置最大化代数G,随机生成NP个个体作为初始群体P(0)。
(2)个体评价。计算群体P(t)中各个个体的适应度。
(3)选择运算。将选择算子作用于群体,根绝个体的适应度,按照一定的规则或方法,选择一些优良个体遗传到下一代群体。
(4)交叉运算。将交叉算子作用于群体你,对选中的成对个体,以某一概率交换它们之间的部分染色体,产生新的个体。
(5)变异运算。将变异算子作用于群体,对选中的个体,以某一概率改变某一个或某一些基因值为其他的等位基因。群体P(t)经过选择、交叉和变异运算之后得到下一代群体P(t+1)。计算其适应度值,并根据适应度值进行排序,准备进行下一次遗传操作。
(6)终止条件判断:若g<=g,则g=g+1,转到步骤(2);若g>G,则进化工程中所得到的具有最大适应度的个体作为最优解输出,终止计算。
群体规模NP
群体规模将影响遗传优化的最终结果以及遗传算法的执行效率。当群体规模NP太小时,遗传优化性能一般不会太好。采用较大的群体规模可以减小遗传算法陷入局部最优解的机会,但较大的群体规模意味着复杂度较高。一般NP取10~200。
交叉概率Pc
交叉概率Pc控制着交叉操作被使用的频率,较大的交叉概率可以增强遗传算法开辟新的搜索区域的能力,但高性能的模式遭到破坏的可能性增大;若交叉概率太低,遗传算法搜索可能陷入迟钝状态。一般Pc取0.25~1.00。
变异概率Pm
变异在遗传算法中属于辅助性的搜索操作,它的主要目的是保持群体的多样性。一般低频度的变异可防止群体中重要基因的可能丢失,高频度的变异将使遗传算法趋于纯粹的随机搜索。通常Pm取0.001~0.1。
遗传运算的终止进化代数G
终止进化代数G表示遗传算法运行结束条件的一个参数,它表示遗传算法运行到指定的进化代数之后就停止运行,并将当前群体中的最佳个体所求问题的最优解输出。一般视具体问题而定,G的取值可在100~1000之间。
此部分内容参考B站up主:一如少年游
遗传算法,有手就行_哔哩哔哩_bilibili
function y = fun(x)
y = sum(x); % 求ymin
end
clc;clear
nVar = 100; % 自变量长度
nPop = 30; % 种群规模
maxIt = 2000; % 最大迭代次数
nPc = 0.8; % 子代比例
nC = round(nPop * nPc / 2) * 2; % 子代规模
nMu = 0.01; % 变异概念
% 结果存放模板
template.x = [];
template.y = [];
% 父代种群结果存放
Parent = repmat(template, nPop, 1);
% 初始化种群
for i = 1 : nPop
Parent(i).x = randi([0, 1], 1, nVar);
Parent(i).y = fun(Parent(i).x);
end
for It = 1 : maxIt
% 子代种群结果存放数组
Offspring = repmat(template, nC/2, 2);
for j = 1 : nC / 2
% 选择
p1 = selectPop(Parent);
p2 = selectPop(Parent);
% 交叉
[Offspring(j, 1).x, Offspring(j, 2).x] = crossPop(p1.x, p2.x);
end
Offspring = Offspring(:);
% 变异
for k = 1 :nC
Offspring(k).x = mutatePop(Offspring(k).x, nMu);
Offspring(k).y = fun(Offspring(k).x);
end
% 合并种群
newPop = [Parent; Offspring];
% 排序
[~, so] = sort([newPop.y], 'ascend');
newPop = newPop(so);
% 筛选
Parent = newPop(1 : nPop);
disp(['迭代次数:', num2str(It), ', 最小值为:', num2str(Parent(1).y)])
end
function p = selectPop(Parent)
% 锦标赛选择法
n = numel(Parent);
index = randperm(n);
p1 = Parent(index(1));
p2 = Parent(index(2));
if p1.y <= p2.y
p = p1;
else
p = p2;
end
end
function [y1, y2] = crossPop(x1, x2)
% 单点交叉
n = numel(x1);
s = randi([1, n - 1]);
y1 = [x1(1 : s) x2(s + 1: end)];
y2 = [x2(1 : s) x1(s + 1: end)];
end
function p = mutatePop(x, mu)
% 单点变异
if rand <= mu
n = numel(x);
s = randi([1, n]);
if x(s) == 0
x(s) = 1;
elseif x(s) == 1
x(s) = 0;
end
end
p = x;
end
2022年11月28日学习感受:感觉只能听懂个大概,up主是按照遗传算法的那个步骤去写的,选择,交叉,变异。需要学习matlab的基础知识。