前言:上一篇文章中我们学习的模拟退火算法是通过模拟物体的物理退火过程得以实现的,今天我们要学习的遗传算法则是通过模拟生物学中物种的进化过程来实现的!
一、遗传算法的基本原理
生物进化选择物种:
“ 物竞天择,适者生存 ” 生动地描述了自然的选择残酷性。能够很好适应当前环境的生物不仅生存了下来,还把它体内的优质“基因”留给了下一代。继承优质基因的“下一代们”不断的适应着新的环境,环境又不断的选择新的适合生存的物种。如此交替循环,经过数代的发展,最终留下来的生物一定是最适合当前环境的!
遗传算法寻找最优解:
遗传算法借鉴了达尔文的生物进化理论和孟德尔的遗传定律,使用“适者生存”的原则,在潜在的解决方案中逐次产生一个近似最优解的方案。在遗传算法的每一代中,根据个体的适应度值进行选择,并根据遗传学法则产生新一代的个体。在这个过程中种群中的个体适应度不断增强,得到解也不断接近最优解!
二、遗传算法的实现
2.1 具体实现步骤:
(1) 根据具体问题确定可行解域,确定一种编码方法,能用数值串或字符串表示 可行解域的每一解。
(2) 确定一个度量好坏的依据,它用一函数表示,叫做适应度函数。
(3)确定进化参数群体规模 N 、交叉概率 pc 、变异概率 pm
2.2遗传算法的一些基本概念:
基因编码(将优化的变量转化为基因的组合表达形式,常见的编码形式有二进制和十进制两种:
二进制编码:
用二进制编码的形式表示实数。
如:用“000000” 到“111111”表示实数[0,63],编码“000000”表示“0”,编码“000001”表示“1”。当然二进制编码不仅可以表示整数,还可以表示小数。
具体步骤是,先把二进制编码表示为整数,然后在把整数映射到要表示的区间。如要用“000000” 到“111111”表示[0,10],“000000”表示0,“000001”表示0.15873,“000010”表示0.31746,相邻两个值的跳跃值约10/63≈0.15873
十进制编码:
用实数进行编码
种群大小N:为便于计算,一般来说,每一代群体的个体数目都取相等。群体规模越大、越容 易找到最优解,但由于受到计算机的运算能力的限制,群体规模越大,计算所需要的时间也相应的增加
遗传概率Pm:又称交叉概率。得到种群中的优质个体后,以某一概率(遗传概率)交换他们之间的部分染色体。遗传概率控制着交叉操作,较大的交叉概率可以增强遗传算法开辟新的搜索领域,但对解的破坏性较大,一般取0.25~1
变异概率Pc:对群体中的每一个个体以某一概率(变异概率)把一小部分基因改变为等位基因。变异能保持群体的多样性,防止重要基因丢失,但变异概率不宜太大,一般取0.001~0.1
适应度函数
用来评价个体优劣的数学函数,一般由目标函数映射成适应度函数,或直接由目标函数来表示个体的适应度
选择遗传个体
根据个体的适应度,按照一定的规则或方法,从第i代个体中选择出出一些优良的个体遗传到i+1代中。选择的个体数为每代种群的个数N。主要有两种选择方法。
直接选择:按照适应度排序,选择适应度最靠前的那部分个体。
概率选择选择法(“轮盘赌”):一种基于比例的选择,利用各个个体适应度所占比例的大小决定其子孙保留的可能性。若某个个体的 i 的适应度为,种群大小为N,则它被选择的概率为:
2.3算法流程图:
三、遗传算法的改进
遗传算法对全局最优解具有强大的搜索能力,但标准遗传算法的局部能力搜索能力相对较差,且容易较早的收敛。所以在处理很多问题时常常和其他算法如模拟退火、禁忌搜索算法、改良圈等其他算法一起使用。
四、遗传算法的应用实例一:寻找函数的极值
问题:寻找下面函数在[0,20]的最大值。
4.1实现步骤:
基因编码:我们用20位的二进制来表示[0,20],相邻两个值之间的跳跃值为:
20/(2^20) ≈0.000002
选择遗传个体:轮盘赌选择
4.2 结果
我们可以看到函数在[0,20]区域内大约在X = 19的位置取得最大值,我们用遗传算法来求解。
可以看到,大约在11代的时候就能找到最优解,可见遗传算法的强大之处。
注:实现代码见文末
五、遗传算法的应用实例二:解决TSP问题
当然,寻找函数的极值还是不能凸显出遗传算法的强大之处。检验优化算法还是得用TSP 来检验,并且这次的城市数量我们也上升到了130个
当然了,只有遗传算法还是不太够滴!所以在遗传算法的基础上,我们又添加了改良圈算法来产生初始解。
5.2 实现步骤:
基因编码:
采用十进制编码,用随机数列作为染色体,其中 0 < Ci< 1 (i =2,3,n-1),C1 = 0,Cn = 1。每一个随机序列都和种群中的一个个体相对应,再按升序排列。例如一个10目标问题的一个染色体为[0, 0.23, 0.82, 0.45, 0.74, 0.87, 0.11, 0.56, 0.69, 0.78, 0.52, 1]的路径为:[ 1 7 2 4 11 8 9 5 10 3 6 12]
改良圈算法产生初始解:
对于初始解:
交换U和V之间的顺序:
计算产生的函数差:
若 < 0,修改后的路径作为新路径,继续修改,若>0,z则沿用当前的路径继续修改。
结果:
寻找函数的极值源代码
clc,clear
N = 50;
L = 20;
pc =0.8;
pm =0.1;
g =100;
xs =20;
xx =0;
f = round(rand(N,L));
for k =1:g
for i = 1:N
u =f (i,:);
m = 0;
for j =1:L
m = u(j)*2^(j-1)+m;
end
x(i) = xx + m*(xs-xx)/(2^L-1);
fit(i) = func1(x(i));
end
maxfit = max(fit);
minfit = min(fit);
rr = find(fit==maxfit);
fbest = f(rr(1,1),:);
xbest = x(rr(1,1));
fit = (fit-minfit)/(maxfit-minfit);
%轮盘赌赋值操作
sum_fit = sum(fit);
fitvaule = fit./sum_fit;
fitvaule = cumsum(fitvaule);
ms = sort(rand(N,1));
fiti = 1;
newi = 1;
while newi <= N
if (ms(newi)) < fitvaule(fiti)
nf(newi,:) = f(fiti,:);
newi = newi +1;
else
fiti = fiti +1;
end
end
%概率交差操作
for i = 1:2:N %选择两个优秀个体
p = rand;
if p <pc
q = round(rand(1,L));
for j =1:L
if q(j) == 1
temp = nf(i+1,j);
nf(i+1,j) = nf(i,j);
nf(i,j) = temp;
end
end
end
end
%变异操作
i =1;
while i <= round(N*pm)
h = randi(N);
for j = 1:round(L*pm)
g = randi(L);
nf(h,g) = ~nf(h,g);
end
i = i+1;
end
f = nf;
f(1,:) =fbest;
value(k) = maxfit;
end
xbest;
xx = 0:0.1:20;
y = sin(2*xx)+cos(3*xx)+xx;
figure
plot(xx,y)
figure
plot(value)
function result = func1(x)
fit = sin(2*x)+cos(3*x)+x;
result = fit;
end
遗传算法求解TSP问题源代码
clc,clear
%导入数据
aa = readmatrix('TSP数据-2.csv');
sj = aa([1:129],[3,4]);
dl =[sj(1,1),sj(1,2)];
sj=[sj;dl];
[n1 ,n2]= size(sj);
sj=sj*pi/180;
d=ones(n1);%计算距离矩阵
for i =1:n1
for j=1:n1
mp=cos(sj(i,1)-sj(j,1))*cos(sj(i,2))*cos(sj(j,2))+sin(sj(i,2))*sin(sj(j,2));
d(i,j)=6370*acos(mp);
end
end
L=130;%基因链长度
N=50;%种群数量
G=100;%代数
Pc=0.1;%变异概率
Pm=0.9;%交叉概率
%通过改良圈算法选取优良父代 A
J = zeros(N,L);%开辟空间存储初始种群
for k=1:N %产生初始种群,种群数量为N个
c=randperm(L-2); %产生初始染色体
c1=[1,c+1,L];
flag=1;
while flag>0
flag=0;
for m=1:L-3
for n=m+2:L-1
if d(c1(m),c1(n))+d(c1(m+1),c1(n+1))<d(c1(m),c1(m+1))+d(c1(n),c1(n+1))
flag=1;
c1(m+1:n)=c1(n:-1:m+1);
end
end
end
end
J(k,c1)=1:L;
end
%计算改良圈初始产生路径的解
pathss = J;
temp1 = 0;
for i=1:(L-1)
temp1 = temp1+d(pathss(1,i),pathss(1,i+1));
end
fprintf('计算改良圈初始产生路径的长度:%8.2f\n',temp1)
J=J/L;
J(:,1)=0;J(:,L)=1;
%遗传算法实现过程
A=J;
for k=1:G %产生 0~1 间随机数列进行编码
B=A;
c=randperm(N);
%交配产生子代 B
for i=1:2:N
p = rand;
if p<Pm
F=2+floor((L-2)*rand(1));
temp=B(c(i),F:L);
B(c(i),F:L)=B(c(i+1),F:L);
B(c(i+1),F:L)=temp;
end
end
%变异产生子代 C
by=find(rand(1,N)<Pc);%依概率Pc选择变异个体
if isempty(by)
by=floor(N*rand(1))+1;
end
C=A(by,:);
L3=length(by);
for j=1:L3
bw=2+floor((L-2)*rand(1,3));
bw=sort(bw);
C(j,:)=C(j,[1:bw(1)-1,bw(2)+1:bw(3),bw(1):bw(2),bw(3)+1:L]);
end
%在父代和子代中选择优良品种作为新的父代
G=[A;B;C];
TL=size(G,1);
[dd,IX]=sort(G,2);temp = zeros(1,TL);
for j=1:TL
for i=1:(L-1)
temp(j)=temp(j)+d(IX(j,i),IX(j,i+1));
end
end
[DZ,IZ]=sort(temp);
A=G(IZ(1:N),:);
end
path=IX(1,:);
fprintf('旅行商经过路径的长度:%8.2f\n',DZ(1))
sj=sj*180/pi;
xx=sj(path,1);yy = sj( path,2);
plot(xx,yy,'- *') %画出巡航路径
text(sj(1,1),sj(1,2),'中心城市','color','r')%标注数据中心点
最后感谢大家的阅读,初来乍到,不周之处请多包涵。如有问题,欢迎在本文下方留言讨论。
如需本文完整程序文件,请加matlab编程爱好者②群获取,在群文件matlab爱好者公众号数据及程序文件夹下的matlab优化算法之遗传算法TSP数据。
参考资料:
[1] 司守奎《数学建模算法与程序》
[2] 姜启源,谢金星,叶俊《数学建模》
[3] 包子阳,余继周《智能优化算法及其MATLAB实例》
封面图片:由 Arek Socha 在Pixabay上发布