目录
2遗传算法
缺点:一旦某个个体的适应值为0,则其选择概率为0,这个个体就不能产生后代。
fitness:待优化的函数
a:自变量下界
b:自变量上界
NP:种群大小
NG:最大进化代数
Pc:杂交概率
Pm:变异概率
eps:自变量离散精度
xm:目标函数取最小值时的自变量值
fv:目标函数的最小值
q:最好的个体选择概率
ksi0:选择压力调节值得初始值
c:选择压力调节值得缩小系数
2.1概述
遗传算法效法基于自然选择的生物进化,是一种模仿生物进化过程的随机方法。遗传算法是从代表问题可能潜在解集的一个种群开始,而一个种群则由经过基因编码的一定数目的个体组成,每个个体实际上是带有染色体特征的实体。染色体作为遗传物质的主要载体,即多个基因的集合,其内部表现(即基因型)是某种基因组合,它决定了个体形状的外部表现。
在一开始需要实现从表现型到基因型的映射即编码工作。由于仿照基因编码的工作很复杂,我们往往进行简化,如二进制编码。初代种群产生之后,按照适者生存和优胜劣汰的原理,逐代演化产生出越来越好的近似解。
在每一代,根据问题域中个体的适应度大小挑选个体,并借助于遗传学的遗传算子进行组合交叉和变异,产生出代表新的解集的种群。
这个过程将导致种群像自然进化一样,后生代种群比前代更加适应于环境,末代种群中的最优个体经过解码,可以作为问题近似最优解。
遗传算法包括三个基本操作:选择、交叉和变异,这些基本操作又有许多不同的方法。
2.1.1选择
选择的含义为确定重组或交叉个体,以及被选个体将产生多少个子代个体。选择的标准一是按照适应度来进行的,适应度的计算有以下两种方法:
(1)按比例的适应度计算;
(2)基于排序的适应度计算。
适应度计算之后是实际的选择,按照适应度进行父代个体的选择,可以挑选以下的算法:
(1)轮盘赌选择;
(2)随机遍历抽样;
(3)局部选择;
(4)截断选择;
(5)锦标赛选择。
2.1.2交叉
交叉是结合来自父代交配种群中的信息产生新的个体。依据个体编码表示方法的不同,可以有以下的算法:
(1)实值重组
- 离散重组;
- 中间重组;
- 线性重组;
- 扩展线性重组。
(2)二进制交叉
- 单点交叉;
- 多点交叉;
- 均匀交叉;
- 洗牌交叉;
- 缩小代理交叉。
2.1.3变异
交叉之后子代经历的变异,实际上是子代基因按小概率扰动产生的变化。依据个体编码表示方法的不同,可以有以下的算法:
(1)实值变异;
(2)二进制变异。
2.2基本遗传算法
[xm,fv] = myGA(fitness,a,b,NP,NG,Pc,Pm,eps)
fitness:待优化的函数
a:自变量下界
b:自变量上界
NP:种群大小
NG:最大进化代数
Pc:杂交概率
Pm:变异概率
eps:自变量离散精度
xm:目标函数取最小值时的自变量值
fv:目标函数的最小值
- 算法原理:(1)用二进制编码来离散自变量,码长根据离散精度来确定。(2)交叉方法采用单点交叉(3)变异是根据变异概率反转子代某个位的值,一般变异为很小的数,在0到0.05之间(4)选择策略采用轮盘赌策略
- 优点:个体的适应值越大,其选择概率越大。因此如果将目标函数作为适应函数,则此遗传算法是求目标函数的最大值。求解一维无约束优化问题
- 缺点:
- 个人见解:主要用来估计极值点的大致位置;遗传算法求得的结果的精度一方面与离散精度有关,另一方面与个体数目有关,离散精度决定了遗传算法能得到最大精度,个体数目越大,求得的结果精度越有可能达到离散精度。
- matlab代码
function [xm,fv] = myGA(fitness,a,b,NP,NG,Pc,Pm,eps)
L - ceil(l0g2((b-a)/eps+1)); %根据离散精度,确定二进制编码需要的码长
x= zeros (NP,L);
for i=1:NP
x(i,:)=Initial(L); %种群初始化
fx(i) = fitness(Dec(a,b,x(i,:),L)); %个体适应值
end
for k=1:NG
sumfx = sum(fx); %所有个体适应值之和
Px = fx/sumfx; %所有个体适应值的平均值
PPX = 0;
PPx(1) = Px(1);
for i=2:NP %用于轮盘赌策略的概率累加
PPx(i) = PPx(i-1) + Px(i);
end
for i=l:NP
sita = rand();
for n=l:NP
if sita <= PPx(n)
SelFather = n; %根据轮盘赌策略确定的父亲
break;
end
end
%%%%1
Selmother = floor(rand()*(NP-1))+1; %随机选择母亲
posCut = floor(rand()*(L-2))+ 1; %随机确定交叉点
r1 = rand();
if rl<=Pc %交叉
nx(i,1:posCut)=x(SelFather,1:posCut);
nx(i,(posCut+1):L) = x(Selmother,(posCut+1):L);
r2 = rand();
%%%%
if r2<= Pm %变异
posMut = round(rand()*(L-1) + 1);
nx(i,posMut)=~nx(i,posMut);
end
%%%%2
else
nx(i,:)=x(SelFather,:);
end
%%%%
end
x= nx;
for i=1:NP
fx(i) = fitness(Dec(a,b,x(i,:),L)); %子代适应值
end
end
fv = -inf;
for i=1:NP
fitx = fitness(Dec(a,b,x(i,:),L));
if fitx > fv
fv = fitx; %取个体中的最好值作为最终结果
xv = Dec(a,b,x(i,:),L);
end
end
function result = Initial(length) %初始化函数
for i=l:length
r = rand();
result(i)= round(r);
end
function y= Dec(a,b,x,L) %二进制编码转换为十进制编码
base = 2.^((L-1):-1:0);
y= dot (base,x);
y= a + y*(b-a)/(2^L-1);
2.3顺序选择遗传算法
fitness:待优化的函数
a:自变量下界
b:自变量上界
NP:种群大小
NG:最大进化代数
Pc:杂交概率
Pm:变异概率
eps:自变量离散精度
xm:目标函数取最小值时的自变量值
fv:目标函数的最小值
%q:最好的个体选择概率
- 算法原理:将选择概率固化,(1)按适应值大小对个体进行排序;(2)定义最好的个体的选择概率为q。
- 优点:每一个个体都有可能被选中从而产生后代
- 缺点:
- 个人见解:
- matlab代码
function [xm,fv] = SBOGA(fitness,a,b,NP,NG,q,Pc,Pm,eps)
L = ceil(log2((b-a)/eps+1)); %根据离散精度,确定二进制编码需要的码长
x = zeros (NP,L);
for i=1:NP
x(i,:)= Initial(L); %种群初始化
fx(i)= fitness(Dec(a,b,x(i,:),L)); %个体适应值
end
%%%%1
for k=1:NG
[sortf,sortx] = sort(fx); %适应值排序
x= x(sortx,:);
fx = fx(sortx);
for i=1:NP %固定选择概率
Px(i) =(1-q)^(NP-i)*q/(1-(1-q)^NP);
end
PPx = 0;
PPx(1) = Px(1);
%%%%
for 1=2:NP %用于轮盘赌策略的概率累加
PPx(i) = PPx(i-1) + Px(i);
end
for i=l:NP
sita = rand();
for n=l:NP
if sita <= PPx(n)
SelFather = n; %根据轮盘赌策略确定的父亲
break;
end
end
Selmother = floor(rand()*(NP-1))+1; %随机选择母亲
posCut = floor(rand()*(L-2))+ 1; %随机确定交叉点
rl = rand();
if rl<=Pc %交叉
nx(i,1:posCut)=x(SelFather,1:poscut);
nx(i,(posCut+1):L) = x(Selmother,(poscut+1):L);
r2 = rand();
if r2 <= Pm %变异
posMut = round(rand()*(L-1)+ 1);
nx(i,posMut)=~nx(i,posMut);
end
else
nx(i,:)=x(SelFather,:);
end
end
x= nx;
for i=1:NP
fx(i)= fitness(Dec(a,b,x(i,:),L)); %子代适应值
end
end
fv = -inf;
for i=1:NP
fitx = fitness(Dec(a,b,x(i,:),L));
if fitx> fv
fv = fitx; %取个体中的最好值作为最终结果
xv = Dec(a,b,x(i,:),L);
end
end
function result = Initial(length) %初始化函数
for i=1:length
r= rand();
result(i)= round(r);
end
function y= Dec(a,b,x,L) %二进制编码转换为十进制编码
base =2.^((L-1):-1:0);
y = dot (base,x);
y=a + y*(b-a)/(2^L-1);
2.4适值函数标定的遗传算法
此为动态线性标定适值函数的遗传算法函数
[xv,fv] = NormFitGA(fitness,a,b,NP,NG,ksi0,c,Pc,Pm,eps)
fitness:待优化的函数
a:自变量下界
b:自变量上界
NP:种群大小
NG:最大进化代数
Pc:杂交概率
Pm:变异概率
eps:自变量离散精度
xm:目标函数取最小值时的自变量值
fv:目标函数的最小值
%ksi0:选择压力调节值得初始值
%c:选择压力调节值得缩小系数
- 算法原理:一般情况下,直接将目标函数作为适值函数,这样比较个体的优劣十分方便。但是很多情况下不能直接将目标函数作为适值函数,例如最小值问题,需将目标函数取反才能作为适值函数。有时由于目标函数之间的相对差别很小,从而各个个体的选择概率差别很小,此时每个个体被选择的几率几乎一样,将导致遗传算法的选择功能被弱化,此时需要对目标函数进行变换。变换方法有:线性标定、幂律标定、对数标定等。
- 优点:对差异很小的目标函数采取了动态变换的方法,提高了遗传算法的选择功能。
- 缺点:
- 个人见解:
- matlab代码
function [xv,fv] = NormFitGA(fitness,a,b,NP,NG,ksi0,c,Pc,Pm,eps)
L = ceil(log2((b-a)/eps+1)); %根据离散精度,确定二进制编码需要的码长
x= zeros(NP,L);
for i=l:NP
x(i,:)= Initial(L); %种群初始化
fx(i)= fitness(Dec(a,b,x(i,:),L)); %个体适应值
end
%%%%1
ksi = ksi0; %选择压力调节值的初始值
for k=1:NG
fmin = min(fx); %群体适应值的最小值
Normfx = fx - fmin*ones(size(fx))+ ksi;%适应值变换
sumfx = sum(Normfx); %所有个体适应值之和
Px = Normfx/sumfx; %所有个体适应值的平均值
PPx = 0;
PPx(1)= Px(1);
%%%%
for i=2:NP %用于轮盘赌策略的概率累加
PPx(i) = PPx(i-1) + Px(i);
end
for i=1:NP
sita = rand();
for n=l:NP
if sita <= PPx(n)
SelFather = n; %根据轮盘赌策略确定的父亲
break;
end
end
Selmother = floor(rand()*(NP-1))+1; %随机选择母亲
posCut = floor(rand()*(L-2))+ 1; %随机确定交叉点
rl = rand();
if rl<=Pc %交叉
nx(i,1:posCut)= x(SelFather,1:posCut);
nx(i,(posCut+1):L) = x(Selmother,(posCut+1):L);
r2 = rand();
if r2 <= Pm %变异
posMut = round(rand()*(L-1) + 1);
nx(i,posMut)=~nx(i,posMut);
end
else
nx(i,:) = x(SelFather,:);
end
end
x= nx;
%%%%2
for i=1:NP
fx(i) = fitness(Dec(a,b,x(i,:),L));
end
ksi = ksi*c; %选择压力调节值的缩小系数
%%%%
end
fv = -inf;
for i=1:NP
fitx = fitness(Dec(a,b,x(i,:),L));
if fitx> fv
fv = fitx; %取个体中的最好值作为最终结果
xv = Dec(a,b,x(i,:),L);
end
end
function result = Initial(length) %初始化函数
for i=1:length
r = rand();
result(i)= round(r);
end
function y = Dec(a,b,x,L) %二进制编码转换为十进制编码
base = 2.^((L-1):-1:0);
y = dot (base,x);
y= a + y*(b-a)/(2^L-1);
2.5大变异遗传算法
[xv,fv] = GMGA(fitness,a,b,NP,NG,Pc,Pm,alpha,Pbm,eps)
fitness:待优化的函数
a:自变量下界
b:自变量上界
NP:种群大小
NG:最大进化代数
Pc:杂交概率
Pm:变异概率
eps:自变量离散精度
xm:目标函数取最小值时的自变量值
fv:目标函数的最小值
%alpha:密集因子
%Pbm:大变异概率
密集因子alpha:用来决定大变异操作的遗传算法在整个优化过程中所占的比重,其数值越接近0.5,大变异操作被调用的越频繁
大变异概率Pbm:概率越大,含大变异操作的遗传算法(即“大变异遗传算法”)的稳定性就越好。但是,这是以牺牲收敛速度为代价的,当其数值等于0.5时,大变异操作就近似蜕化成随机搜索。
- 算法原理:理论上,遗传算法中的变异操作可以使算法避免“早熟”。但是为了保证算法的稳定性,变异操作的变异概率通常取值很小,所以算法一旦出现“早熟”,单靠传统的变异操作需要很多代才能变异出一个不同于其他个体的新个体。
- 操作思路:当某代中所有个体集中在一起是,我们以一个远大于通常的变异概率的概率执行一次变异操作,具有大变异概率的变异操作能够随机、独立地产生许多新个体,从而使整个种群脱离“早熟”。
- 优点:
- 缺点:
- 个人见解:用于求函数最大值
- matlab代码
function [xv,fv] = GMGA(fitness,a,b,NP,NG,Pc,Pm,alpha,Pbm,eps)
L = ceil(log2((b-a)/eps+1)); %根据离散精度,确定二进制编码需要的码长
x= zeros(NP,L);
for i=1:NP
x(i,:)= Initial(L); %种群初始化
fx(i) = fitness(Dec(a,b,x(i,:),L)); %个体适应值
end
for k=l:NG
sumfx = sum(fx); %所有个体适应值之和
Px = fx/sumfx; %所有个体适应值的平均值
%%%%1
[fmax,xmax] = max(fx); %群体适应值最大值
if k<NG/2 %前半部分进化
if fmax*alpha<favg %个体集中程度
rm = rand();
if rm < Pbm %大变异,但是保留最优个体xmax不变异
for i=1:(xmax-1)
gmPos = round(rand*(L-1)+1); %变异位
x(i,gmPos) =~x(i,gmPos); %取反变异
end
fx(i)= fitness(Dec(a,b,x(i,:),L));
for i=(xmax+1):NP
gmPos = round(rand*(L-1)+1); %变异位
x(i,gmPos) =~x(i,gmPos); %取反变异
fx(i) = fitness(Dec(a,b,x(i,:),L));
end
continue;
end
end
end
Px = fx/sumfx;
%%%%
PPx = 0;
PPx(1) = Px(1);
for i=2:NP %用于轮盘赌策略的概率累加
PPx(i) = PPx(i-1) + Px(i);
end
for i=l:NP
sita = rand();
for n=l:NP
if sita <= PPx(n)
SelFather = n; %根据轮盘赌策略确定的父亲
break;
end
end
Selmother = floor(rand()*(NP-1))+1; %随机选择母亲
posCut = floor(rand()*(L-2))+ 1; %随机确定交叉点
rl = rand();
if rl<=Pc %交叉
nx(i,1:posCut)= x(SelFather,l:posCut);
nx(i,(posCut+1):L) = x(Selmother,(poscut+1):L):
r2 = rand();
if r2 <= Pm %变异
posMut = round(rand()*(L-1) + 1);
nx(i,posMut) =~nx(i,posMut);
else
nx(i,:)=x(SelFather,:);
end
end
x= nx;
for i=1:NP
fx(i)= fitness(Dec(a,b,x(i,:),L));%子代适应值
end
end
fv = -inf;
for i=1:NP
fitx = fitness(Dec(a,b,x(i,:),L));
if fitx> fv
fv = fitx; %取个体中的最好值作为最终结果
xv = Dec(a,b,x(i,:),L);
end
end
function result = Initial(length) %初始化函数
for i=l:length
r = rand();
result(i)= round(r);
end
function y= Dec(a,b,x,L) %二进制编码转换为十进制编码
base = 2.^((L-1):-1:0);
y = dot (base,x);
y= a + y*(b-a)/(2^L-1);
2.6自适应遗传算法
[xv,fv] = AdapGA(fitness,a,b,NP,NG,Pcl1,Pc2,Pm1,Pm2,eps)
fitness:待优化的函数
a:自变量下界
b:自变量上界
NP:种群大小
NG:最大进化代数
Pc1,Pc2:杂交常数
Pm1,Pm2:变异常数
eps:自变量离散精度
xm:目标函数取最小值时的自变量值
fv:目标函数的最小值
- 算法原理:遗传算法的参数中交叉概率和变异概率的选择是影响遗传算法行为和性能的关键所在,直接影响算法的收敛性,交叉概率越大,新个体产生的速度就越快。然而,交叉概率过大时遗传模式被破坏的可能性也就越大,使得具有高适应度的个体结构很快就会被破坏;但是如果交叉概率过小,会使搜索过程缓慢,以至停滞不前。
对于变异概率来说,如果其取值过小,就不易产生新的个体结构;如果其取值过大,那么遗传算法就变成了纯粹的随机搜索算法。针对不同的优化问题,需要反复试验来确定交叉概率和变异概率,一般很难找到适应于每个问题的最佳值。
Srinvivas等提出一种自适应遗传算法,交叉概率和变异概率能够随适应度自动改变。当种群各个体适应度趋于一致或者趋于局部最优时,使交叉概率和变异概率二者增加、而当群体适应度比较分散时,使交叉概率和变异概率减少。
同时,对于适应值高于群体平均适应值得个体,对应于较低的交叉概率和变异概率,使该个体得以保护进入下一代;而低于平均适应值的个体,相对应于较高的交叉概率和变异概率,使该个体被淘汰掉。因此,自适应遗传算法能够提供相对某个解得最佳交叉概率和变异概率。
- 优点:
- 缺点:
- 个人见解:
- matlab代码
function [xv,fv] = AdapGA(fitness,a,b,NP,NG,Pcl1,Pc2,Pm1,Pm2,eps)
L = ceil(log2((b-a)/eps+1)); %根据离散精度,确定二进制编码需要的码长
x = zeros (NP,L);
for i=1:NP
x(i,:)= Initial(L); %种群初始化
fx(i) = fitness(Dec(a,b,x(i,:),L)); %个体适应值
end
for k=1:NG
sumfx = sum(fx); %所有个体适应值之和
Px = fx/sumfx; %所有个体适应值的平均值
PPx = 0;
PPx(1) = Px(1);
for i=2:NP %用于轮盘赌策略的概率累加
PPx(i) = PPx(1-1) + Px(i);
end
for i=1:NP
sita = rand();
for n=l:NP
if sita <= PPx(n)
SelFather = n; %根据轮盘赌策略确定的父亲
break;
end
end
%%%%
Selmother = floor(rand()*(NP-1))+1; %随机选择母亲
posCut = floor(rand()*(L-2))+ 1; %随机确定交叉点
favg = sumfx/NP; %群体平均适应值
fmax = max(fx); %群体最大适应值
Fitness_f = fx(SelFather); %交叉的父亲适应值
Fitness_m = fx(Selmother); %交叉的母亲适应值
Fm = max(Fitness_f,Fitness_m); %交叉双方较大的适应值
if Fm>=favg %自适应交叉概率
PC = Pcl*(fmax - Fm)/(fmax - favg);
else
Pc = Pc2;
end
rl = rand();
if rl<=Pc %交叉
nx(i,1:posCut)= x(SelFather,1:poscut);
nx(i,(posCut+1):L) = x(Selmother,(posCut+1):L);
fmu = fitness(Dec(a,b,nx(i,:),L));
if fmu>=favg %自适应变异概率
Pm = Pml*(fmax - fmu)/(fmax - favg);
else
Pm = Pm2;
end
r2 = rand();
%%%%
if r2<= Pm %变异
posMut = round(rand()*(L-1) + 1);
nx(i,posMut)=~nx(i,posMut);
end;
else
nx(i,:)= x(SelFather,:);
end
end
x= nx;
for i=1:NP
fx(i) = fitness(Dec(a,b,x(i,:),L));
end
end
fv = -inf;
for i=1:NP
fitx = fitness(Dec(a,b,x(i,:),L));
if fitx> fv
fy = fitx; %取个体中的最好值作为最终结果
xv = Dec(a,b,x(i,:),L);
end
end
function result = Initial(length) %初始化函数
for i=l:length
r = rand();
result(i)= round(r);
end
function y= Dec(a,b,x,L) %二进制编码转换为十进制编码
base = 2.^((L-1):-1:0);
y= dot (base,x);
y= a + y*(b-a)/(2^L-1);
2.7双切点交叉遗传算法
[xv,fv] = DblGEGA(fitness,a,b,NP,NG,Pc,Pm,eps)
fitness:待优化的函数
a:自变量下界
b:自变量上界
NP:种群大小
NG:最大进化代数
Pc:杂交概率
Pm:变异概率
eps:自变量离散精度
xm:目标函数取最小值时的自变量值
fv:目标函数的最小值
- 算法原理:2.2-2.6的遗传算法都是单点交叉遗传,单点交叉遗传使得父代双方交换基因量较大,有时候很容易破坏优秀个体,而双切点交叉相对单点交叉来说,父代双方交换的基因量较小,有利于优秀个体的保留。
- 优点:继承父代的优秀个体。
- 缺点:
- 个人见解:利用双切点遗传算法求解一维无约束优化问题
- matlab代码
function [xv,fv] = DblGEGA(fitness,a,b,NP,NG,Pc,Pm,eps)
L = ceil(log2((b-a)/eps+1)); %根据离散精度,确定二进制编码需要的码长
x = zeros (NP,L);
for i=1:NP
x(i,:)= Initial(L); %种群初始化
fx(i) = fitness(Dec(a,b,x(i,:),L)); %个体适应值
end
for k=1:NG
sumfx = sum(fx); %所有个体适应值之和
Px = fx/sumfx; %所有个体适应值的平均值
PPx = 0;
PPx(1) = Px(1);
for i=2:NP %用于轮盘赌策略的概率累加
PPx(i) = PPx(1-1) + Px(i);
end
for i=1:NP
sita = rand();
for n=l:NP
if sita <= PPx(n)
SelFather = n; %根据轮盘赌策略确定的父亲
break;
end
end
%%%%1
Selmother = floor(rand()*(NP-1))+1; %随机选择母亲
posCut1 = round(rand()*(L-2))+ 1; %随机确定交叉位置 1
posCut2 = round(rand()*(L-2))+ 1; %随机确定交叉位置 2
while posCut2 == posCutl %保证两个交叉位置不同
posCut2 = round(rand()*(L-2))+ 1;
end
posCutmax = max(posCut1,posCut2); %确定两个交叉位置中的较大值
posCutmin = min(posCut1,posCut2); %确定两个交叉位置中的较小值
rl = rand();
if rl<=Pc %交叉
nx(i,1:posCutmin)= x(SelFather,1:posCutmin); %交换posCutmin 到posCutmax之间的部分
nx(i,(posCutmin+1):posCutmax) = x(Selmother,(posCutmin+1):posCutmax);
if posCutmax<L
nx(i,(posCutmax+1):L) = x(SelFather,(posCutmax+1):L);
end
r2 = rand();
%%%%
if r2<= Pm %变异
posMut = round(rand()*(L-1) + 1);
nx(i,posMut)=~nx(i,posMut);
end
else
nx(i,:)= x(SelFather,:);
end
end
x= nx;
for i=1:NP
fx(i) = fitness(Dec(a,b,x(i,:),L));
end
end
fv = -inf;
for i=1:NP
fitx = fitness(Dec(a,b,x(i,:),L));
if fitx> fv
fy = fitx; %取个体中的最好值作为最终结果
xv = Dec(a,b,x(i,:),L);
end
end
function result = Initial(length) %初始化函数
for i=l:length
r = rand();
result(i)= round(r);
end
function y= Dec(a,b,x,L) %二进制编码转换为十进制编码
base = 2.^((L-1):-1:0);
y= dot (base,x);
y= a + y*(b-a)/(2^L-1);
2.8多变异位自适应遗传算法
[xv,fv] = MMAdapGA(fitness,a,b,NP,NG,Pc1,Pc2,Pm1,Pm2,eps)
fitness:待优化的函数
a:自变量下界
b:自变量上界
NP:种群大小
NG:最大进化代数
Pc:杂交概率
Pm:变异概率
eps:自变量离散精度
xm:目标函数取最小值时的自变量值
fv:目标函数的最小值
- 算法原理:顾名思义,多变异位自适应遗传算法就是在自适应遗传算法中引入多位变异,以增加种群的多样性。在前面的算法中,都是采用的单变异位,即将自变量的二进制表示的某位取反,多变异位是将自变量的二进制表示的多个位取反。
- 优点:灵活性高
- 缺点:
- 个人见解:
- matlab代码
function [xv,fv] = MMAdapGA(fitness,a,b,NP,NG,Pc1,Pc2,Pm1,Pm2,eps)
L = ceil(log2((b-a)/eps+1)); %根据离散精度,确定二进制编码需要的码长
x = zeros (NP,L);
for i=1:NP
x(i,:)= Initial(L); %种群初始化
fx(i) = fitness(Dec(a,b,x(i,:),L)); %个体适应值
end
for k-1:NG
sumfx = sum(fx); %所有个体适应值之和
Px = fx/sumfx; %所有个体适应值的平均值
PPx = 0;
PPx(1) = Px(1);
for i=2:NP %用于轮盘赌策略的概率累加
PPx(i) = PPx(1-1) + Px(i);
end
for i=1:NP
sita = rand();
for n=l:NP
if sita <= PPx(n)
SelFather = n; %根据轮盘赌策略确定的父亲
break;
end
end
%%%%1
Selmother = floor(rand()*(NP-1))+1; %随机选择母亲
posCut = floor(rand()*(L-2))+ 1; %随机确定交叉点
favg = sumfx/NP; %群体平均适应值
fmax = max(fx); %群体最大适应值
Fitness_f = fx(SelFather); %交叉的父亲适应值
Fitness_m = fx(Selmother); %交叉的母亲适应值
Fm = max(Fitness_f,Fitness_m); %交叉双方较大的适应值
if Fm>=favg %自适应交叉概率
PC = Pcl*(fmax - Fm)/(fmax - favg);
else
Pc = Pc2;
end
rl = rand();
if rl<=Pc %交叉
nx(i,1:posCut)= x(SelFather,1:poscut);
nx(i,(posCut+1):L) = x(Selmother,(posCut+1):L);
fmu = fitness(Dec(a,b,nx(i,:),L));
if fmu>=favg %自适应变异概率
Pm = Pml*(fmax - fmu)/(fmax - favg);
else
Pm = Pm2;
end
%%%%
%%%%2
r2 = rand();
if r2 <= Pm %变异
if fmax ~= fmin %随机产生变异位置的个数
numMut = round( L*(fmax-fmu)/(fmax-fmin)/3);
else %如果群体中的最大值等于最小值,只产生一个变异位
numMut = 1;
end
intArr = 1:L;
posMut = zeros(1,numMut);
for j=1:numMut %随机产生变异的位置编号
tmp = round(rand()*(L- j) + 1);
posMut(j)=intArr(tmp);
intArr=[intArr(1:(tmp-1))intArr((tmp+1):(L-j+1))]; %可能是错的
end
for j=1:numMut %对变异位进行取反
nx(i,posMut(j))=~nx(i,posMut(j));
end
end
%%%%
else
nx(i,:)=x(SelFather,:);
end
end
x=nx;
for i=1:NP
fx(i)= fitness(Dec(a,b,x(i,:),L));
end
end
%%%%3
fv = -inf;
for i=1:NP
fx(i) = fitness(Dec(a,b,x(i,:),L));
end
%%%%
fv = -inf;
for i=1:NP
fitx = fitness(Dec(a,b,x(i,:),L));
if fitx> fv
fv = fitx; %取个体中的最好值作为最终结果
xv = Dec(a,b,x(i,:),L);
end
end
function result = Initial(length) %初始化函数
for i=l:length
r = rand();
result(i)= round(r);
end
function y= Dec(a,b,x,L) %二进制编码转换为十进制编码
base = 2.^((L-1):-1:0);
y= dot (base,x);
y= a + y*(b-a)/(2^L-1);
%个人总结,仅供参考。如有补充,欢迎交流%