遗传算法是模拟生物在自然环境下遗传的过程而形成的自适应全局优化搜索算法。如果把某个问题的可行域看作是一个族群,目标函数看作是自然选择的条件,那么,这个族群通过一代又一代的繁衍和进化最终变成最接近筛选条件的样子。遗传算法就是利用了这个思想。
在求解问题的过程中,将问题的可行解的全体看作是初始种群,目标函数作为适应度函数来进行筛选,通过一次又一次的迭代缩小可行解的范围,在该范围中确定最优解的位置。当然,这种方法得到的最优解往往都是最优解的近似或是局部的最优解,过于繁复的迭代也许也是它的一个缺点,但不可否认的是,遗传算法具有强大的适应性,它能够很好地解决各类问题,如大规模的优化问题,TSP问题等。
使用遗传算法还有一个好处,或者说这类启发式算法都拥有的优势就是不需要清楚某一类问题具体的求解方法,它就是一种迭代过程,通过纯粹的迭代实现找到最优解的过程。以优化问题为例,通常的线性规划问题是通过单纯形法来求解,有着严谨的求解过程,而启发式算法则是通过一步又一步的迭代来实现这个过程。
遗传算法的核心步骤只有三个,一个是种群的选取,一个是“基因”的交叉,还有一个是基因的变异。其计算思路如下:
1、选择初始种群
2、计算适应度函数(目标函数),将其归一化后作为下一代选取的概率
3、进行交叉操作(可以基于概率,也可以基于其他)
4、进行变异操作
5、重复2-4,直到达到循环条件(如迭代次数或误差小于某个值)
以下为两个示例,第一个是通过遗传算法求解0-1规划问题;第二个是通过遗传算法求解TSP问题。
%利用遗传算法求解目标规划问题
clear all;
close all;
clc;
c=[2 -1];%目标规划系数
A=-[5 4;-3 1];
b=-[20;3];
NP=500;%种群数目
L=length(c);%基因数目
Xs=20;%上限
Xx=0;%下限
G=1000;%最大遗传代数
Pc=0.8;%交叉概率
Pm=0.2;%变异概率
nf=zeros(NP,L);%储存子种群
f=randi([0,Xs],NP,L);%初始赋值
F=[];%储存可行解
count=0;
for k=1:G
count=count+1;
nn=0;
for i=1:NP
d(:,i)=A*f(i,:)';
m=min(d(:,i)-b);
if m>=0
nn=nn+1;
F(nn,:)=f(i,:);%筛选合适的种群
end
end
%%%%%%%%%%%%%%%%%%将筛选合适的种群扩充%%%%%%%%%%%%%%%%%%%
[aa,bb]=size(F);
while aa<NP
nnper=randperm(nn);
if length(nnper)>=2
AA=F(nnper(1),:);
BB=F(nnper(2),:);
else
AA=F(nnper(1),:);
BB=F(nnper(1),:);
end
F=[F;AA;BB];
[aa,bb]=size(F);
end
if aa>NP%保证种群数为NP
F=F(1:NP,:);
end
f=F;
for i=1:NP
Fit(i)=Hanshu(c,f(i,:));
end
MaxFit=max(Fit);
MinFit=min(Fit);
rr=find(Fit==MinFit);
fBest=Fit(rr(1,1));
xBest=f(rr(1,1),:);
%%%%%%%%%%%%%%%%%%%%%%%%%交叉操作%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
for i=1:2:NP
p=rand;
if p<Pc%满足交叉条件
q=randi([0,1],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(NP*Pm)
h=randi([1,NP],1,1);%随机选取一个染色体
for j=1:round(L*Pm)
g=randi([1, L],1,1);%随机选取需要变异的基因
nf(h,g)=0;
end
i=i+1;
end
f=nf;
f(1,:)=xBest;
trace(k)=MinFit;
F=[];
end
figure
xlabel('迭代次数');
ylabel('目标值函数');
title('适应度进化曲线');
plot(trace)
fBest
xBest
A*xBest'
目标函数部为:
function result = Hanshu(f,x)
%HANSHU 此处显示有关此函数的摘要
% 此处显示详细说明
result=0;
for i=1:length(f)
result=f(i)*x(i)+result;
end
end
用MATLAB解决TSP问题代码如下:
%旅行商问题
%问题描述:
% 旅行商问题(TSP问题)。假设有一个旅行商人要拜访全国31个省会城市,
% 他需要选择所要走的路径,路径的限制是每个城市只能拜访一次,而且最
% 后要回到原来出发的城市。对路径选择的要求是:所选路径的路程为所有路径
% 之中的最小值。
%全国31个省会城市的坐标为
% [1304 2312;3639 1315;4177 2244;3712 1399;3488 1535;3326 1556;3238 1229;
% 4196 1004;4312 790;4386 570;3007 1970;2562 1756;2788 1491;2381 1676;1332 695;
% 3715 1678;3918 2179;4061 2370;3780 2212;3676 2578;4029 2838;4263 2931;3429 1908;
% 3507 2367;3394 2643;3439 3201;2935 3240;3140 3550;2545 2357;2778 2826;2370 2975]。
%%%%%%%%%%%%%%%%%%%%%%%%%%遗传算法求解旅行商问题%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%初始化%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clear all
close all
clc;
C=[1304 2312;3639 1315;4177 2244;3712 1399;3488 1535;3326 1556;3238 1229;
4196 1004;4312 790;4386 570;3007 1970;2562 1756;2788 1491;2381 1676;1332 695;
3715 1678;3918 2179;4061 2370;3780 2212;3676 2578;4029 2838;4263 2931;3429 1908;
3507 2367;3394 2643;3439 3201;2935 3240;3140 3550;2545 2357;2778 2826;2370 2975];
NP=500;
N=31;%基因维数
G=10000;%迭代数
N=size(C,1);%城市个数
D=zeros(N);%任意城市间的距离矩阵
%计算城市间距离矩阵
for i=1:N
for j=1:N
D(i,j)=sqrt((C(i,1)-C(j,1))^2+(C(i,2)-C(j,2))^2);
end
end
f=zeros(NP,N);%储存种群
for i=1:NP
f(i,:)=randperm(N);
end
R=f(1,:);%储存最优种群
len=zeros(NP,1);%储存径路长度
fitness=zeros(NP,1);%储存归一化适应值
gen=0;%迭代次数
while gen<G
for i=1:NP
len(i,1)=D(f(i,N),f(i,1));
for j=1:(N-1)
len(i,1)=len(i,1)+D(f(i,j),f(i,j+1));
end
end
Maxlen=max(len);%最短路径
Minlen=min(len);%最短路径
%%%%%%%%%%%%%%%%%%%%更新最短路径%%%%%%%%%%%%%%%%%%%%%%
rr=find(len==Minlen);
R=f(rr(1,1),:);
%%%%%%%%%%%%%%%%%%%计算归一化适应值%%%%%%%%%%%%%%%%%%%%
for i=1:length(len)
fitness(i,1)=-(len(i,1)-Maxlen)/(Maxlen-Minlen);
end
%%%%%%%%%%%%%%%%%%%%%选择操作%%%%%%%%%%%%%%%%%%%%%%%%%%
nn=0;
for i=1:NP
if fitness(i,1)>=rand
nn=nn+1;
F(nn,:)=f(i,:);
end
end
[aa,bb]=size(F);
while aa<NP
nnper=randperm(nn);
A=F(nnper(1),:);
B=F(nnper(2),:);
%%%%%%%%%%%%%%%%%%%%交叉操作%%%%%%%%%%%%%%%%%%%%%
W=ceil(N/10);%交叉点个数
p=unidrnd(N-W+1);%随机选择交叉范围,从p到p+W
for i=1:W
x=find(A==B(p+i-1));
y=find(B==A(p+i-1));
temp=A(p+i-1);
A(p+i-1)=B(p+i-1);
B(p+i-1)=temp;
temp=A(x);
A(x)=B(y);
B(y)=temp;
end
%%%%%%%%%%%%%%%%%%%%变异操作%%%%%%%%%%%%%%%%%%%%%
p1=floor(1+N*rand());
p2=floor(1+N*rand());
while p1==p2
p1=floor(1+N*rand());
p2=floor(1+N*rand());
end
tmp=A(p1);
A(p1)=A(p2);
A(p2)=tmp;
tmp=B(p1);
B(p1)=B(p2);
B(p2)=tmp;
F=[F;A;B];
[aa,bb]=size(F);
end
if aa>NP
F=F(1:NP,:);
end
f=F;
f(1,:)=R;
F=[];
gen=gen+1;
Rlength(gen)=Minlen;
end
figure
for i=1:N-1
plot([C(R(i),1),C(R(i+1),1)],[C(R(i),2),C(R(i+1),2)],'bo-');
hold on;
end
title('最短化距离:',num2str(Minlen));
figure
plot(Rlength)
xlabel("迭代次数");
ylabel('目标函数');
title('适应度进化曲线');
R
画出来的图稍显不靠谱的原因是因为计算长度没有考虑到第一个点与最后一个点之间的距离,运算结果如图所示:
由于我也是才开始接触这些算法(本科时没有参加建模接触这些还蛮可惜的),觉得很有意思的同时也深感需要学习的有很多,以及自己对这些算法的理解也稍显浅薄,如有不对之处还请指出。
参考:《智能优化算法及其MATLAB实例》——包子阳