备战数学建模37-遗传算法GA(攻坚战1)

本文详细介绍了遗传算法的概念,包括基本过程、选择、交叉和变异操作,通过实例展示如何用遗传算法求解函数极值问题、旅行商问题和背包问题。通过遗传算法求解旅行商问题和0-1背包问题的代码,揭示了算法在实际优化问题中的应用。
摘要由CSDN通过智能技术生成

目录

一、遗传算法的概念

1.1、基本概念

 1.2、遗传算法的基本过程

 1.3、遗传算法的具体步骤

二、遗传算法经典案例

2.1、遗传算法求解函数极大值问题

2.2、遗传算法求解函数极小值问题

2.3、遗传算法求解旅行商问题(TSP)

2.4、遗传算法求解背包问题


一、遗传算法的概念

1.1、基本概念

遗传算法(Genetic Algorithm,GA):模仿生物的遗传进化原理,通过选择、交叉、变异等操作,使得种群个体的适应性不断提高,物竞天择,适者生存。智能算法,全局搜索寻优。

遗传算法的特点如下:

 遗传算法的应用领域比较广泛,具体涉及的应用领域如下:

我们看三个概念,即个体,种群,适应度。初始解组成的是个体,多个个体组成的称为种群,适应度是指衡量个体适应高低的,适应度函数一般就是指的目标函数。

 下面看一下编码和解码的概念,本文中的编码和解码如下,编码是指将原来的个体改变成能进行选择,交叉,和变异等操作的染色体的过程。而解码就是将染色体转换成为原始的个体,即最优解。编码是遗传算法解决问题的先决条件和关键步骤,常用的编码方式有:二进制编码,浮点数编码等。一般来说,二进制编码比浮点型编码的搜索能力更强,浮点型编码在种群多样性的操作更具多样性。

下面看一下遗传操作的选择,交叉与变异。选择操作就是选择好的进行遗传,交叉就是随机配对,变异就是改变基因到其对应的基因。

 1.2、遗传算法的基本过程

遗传算法的基本过程如下:主要包括:收集问题参数并编码成染色体,初始化种族群体,通过选择交叉,变异等遗传操作更新群体,并计算群体的适应度,直到达到迭代次数或者适应度值不发生改变,则终止循环,并对染色体进行解码,即可得到问题的最优解。

下面看一下遗传算法的具体步骤:

首先,我们需要确定决策变量和约束条件,这个通常根据题意获得。然后建立模型,需要确定目标函数,然后需要找出个体,并对个体进行编码,编码是非常重要的,常用的编码方式是二进制编码。

标准的遗传算法基本是采用二进制编码,就是将个体(决策变量)用二进制串连在一起,构成染色体。编码完成,最后留下满足适应度函数的染色体后,还需要进行解码成个体,所以需要确定解码方法。其实就是还原成原来的决策变量。

然后,我们需要确定个体适应度的量化方法,即确定适应度函数,通过适应度函数去求解最优的决策变量,一般比较常用的就是直接将目标函数作为适应度函数,当然也有其它方法去确定适应度函数。

 

 

有了适应度函数后,我们就可以确定选择,交叉和变异的方式,个体选择常用的方法是按比例适应度分配,个体的适应度在总适应度的比例越大,即被选取的概率越大,遗产因子就会在种群中逐渐扩大。

计算出每个个体的选择概率后,我们就使用轮盘赌法进行选择,其实就是概率越大,轮盘所占比例越大,被选中的可能越大。

遗传的相关操作除了选择之外,还有交叉和变异,我们下面看一下交叉操作,交叉其实就是序列的交换,交叉率不宜过大,也不宜过小,一般取0.4-0.9。

 

 下面看一下变异操作,对于二进制编码的变异,就是将1变成0,或者将0变成1,也应该选取合适的变异率,变异率过大和过小都不好。

 

 1.3、遗传算法的具体步骤

 遗传算法的具体步骤如下:首先对个体编码成染色体,初始化群体并计算解码后的适应值,然后进行遗传操作形成下一代群体, 判断是否满足要求,不满足则继续迭代,直到满足要求或者达到迭代次数。

二、遗传算法经典案例

2.1、遗传算法求解函数极大值问题

 用标准遗传算法求函数f(x)=x+10sin(5x)+7cos(4x) 的最大值,其中 x 的取值范围为[0,10]。这是一个有多个局部极值的函数。

下面是使用遗传算法求解该函数模型最大值的具体步骤:

(1)初始化种群数目为 NP=50,染色体的编码方式选择二级制编码,二进制编码长度为 L=20,遗传算法的最大进化迭代数为 G=100,交叉概率 取Pc=0.8,变异概率取Pm=0.1。

(2)产生初始种群,将二进制编码转换成十进制,计算个体适应度值,并进行归一化;采用基于轮盘赌的选择操作、基于概率的交叉和变异操作,产生新的种群,并把历代的最优个体保留在新种群中,进行下一步遗传操作。

(3)判断是否满足终止条件:若满足,则结束搜索过程,输出优化值;若不满足,则继续进行迭代优化。

优化结束后,其适应度进化曲线如下图所示,最优个体 x= 7.8569,函数 f(x)的最大值为 24.8554。这个值不是固定的,每次执行都会有些许波动。

遗传算法的具体流程图如下:

 完整的matlab代码如下,注释很全:

%遗传算法求函数极值
clear 
clc
NP = 50; %种群数量
L = 20; %二进制位串长度
Pc = 0.8; %交叉率
Pm = 0.1; %变异率
G = 100; %最大遗传迭代次数
Xs = 10; %个体最小值
Xx = 0; %个体最大值
f = randi([0,1],NP,L); %随机获得初始种群
%遗传算法
for k = 1:G
    for i = 1:NP
        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) ; %对适应度进行求和
    fitvalue = Fit./sum_Fit; %求每个适应度被选中的概率
    fitvalue = cumsum(fitvalue) ; %得到累加后的概率
    ms = sort(rand(NP,1)) ; %随机生成概率值,并由小到大排序
    fiti = 1;
    newi = 1;
    while newi <= NP
        if ms(newi) < fitvalue(fiti) %如果随机生成的概率值小于被选中的概率
            nf(newi,:) = f(fiti,:); %找到选择出来的染色体
            newi = newi+1;
        else %不满足条件,继寻找合适的染色体
            fiti = fiti+1;
        end
    end
    %交叉操作,就是二进制对应0和1的互换
    for i = 1:2:NP  %遍历种群
        p = rand ; %随机产生的一个概率
        if p > Pc %要保证随机产生的概率大于交叉率
            q = rand(1,L);
            for j = 1:L
                if q(j)==1 %只要随机产生的位置等于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) =~ nf(h,g); %取反变异
        end
        i = i+1;
    end
    f = nf; %更新种群
    f(1,:) = fBest; %保留最优个体在新种群中
    trace(k) = maxFit; %保存最优的适应度
end
disp('最优个体如下:') ;
disp(xBest) ;
disp('函数最大值:') ;
disp(func1(xBest)) ;
figure
plot(trace)
xlabel('迭代次数')
ylabel('目标函数值')
title('适应度进化曲线')

适应度函数即目标函数如下:

function result = func1(x)
fit = x+10*sin(5*x)+7*cos(4*x);
result = fit;
end

迭代过程的适应度进行如下,最终的值在24.85左右,即函数的最值为24.85左右。

2.2、遗传算法求解函数极小值问题

(1)初始化种群数目为 NP=100,染色体的编码方式选择二级制编码,二进制编码长度为 L=10,遗传算法的最大进化迭代数为 G=1000,交叉概率 取Pc=0.8,变异概率取Pm=0.1。

(2)产生初始种群,将二进制编码转换成十进制,计算个体适应度值;采用基于轮盘赌的选择操作、基于概率的交叉和变异操作,产生新的种群,并把历代的最优个体保留在新种群中,进行下一步遗传操作。

(3)判断是否满足终止条件:若满足,则结束搜索过程,输出优化值;若不满足,则继续进行迭代优化。

%遗传算法求函数极值
clear 
clc
NP = 100; %种群数量
L = 10; %二进制位串长度
Pc = 0.8; %交叉率
Pm = 0.1; %变异率
G = 1000; %最大遗传迭代次数
Xs = 20; %个体上限
Xx = -20; %个体下线
f = randi([0,1],NP,L); %随机获得初始种群
%遗传算法
for k = 1:G
    for i = 1:NP
        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) = -func2(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) ; %对适应度进行求和
    fitvalue = Fit./sum_Fit; %求每个适应度被选中的概率
    fitvalue = cumsum(fitvalue);  %得到累加后的概率
    ms = sort(rand(NP,1)) ; %随机生成概率值,并由小到大排序
    fiti = 1;
    newi = 1;
    while newi <= NP
        if ms(newi) < fitvalue(fiti) %如果随机生成的概率值小于被选中的概率
            nf(newi,:) = f(fiti,:); %找到选择出来的染色体
            newi = newi+1;
        else %不满足条件,继寻找合适的染色体
            fiti = fiti+1;
        end
    end
    %交叉操作,就是二进制对应0和1的互换
    for i = 1:2:NP  %遍历种群
        p = rand ; %随机产生的一个概率
        if p > Pc %要保证随机产生的概率大于交叉率
            q = rand(1,L);
            for j = 1:L
                if q(j)==1 %只要随机产生的位置等于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) =~ nf(h,g); %取反变异
        end
        i = i+1;
    end
    f = nf; %更新种群
    f(1,:) = fBest; %保留最优个体在新种群中
    trace(k) = -maxFit; %保存最大的适应度
end
disp('最优个体如下:') ;
disp(xBest) ;
disp('函数最小值:') ;
disp(func2(xBest)) ;
figure
plot(trace)
xlabel('迭代次数')
ylabel('目标函数值')
title('适应度进化曲线')

适应度函数如下:

function result=func2(x)
summ=sum(x.^2);
result=summ;
end

运行结果如下:

 

2.3、遗传算法求解旅行商问题(TSP)

[旅行商问题](TSP)。假设有一个旅行商人要拜访全国31个省会城市,他需要选择所要走的路径,路径的限制是每个城市只能拜访一次,而且最后要回到原来出发的城市。对路径选择的要求是:所选路径的路程为所有路径之中的最小值。全国31个省会城市的坐标为[1304 2312;3639 1315;4177 2244;37121399;3488 1535;3326 1556;3238 1229;4196 1004;4312 790;4386 570;3007 1970;2562 1756;2788 1491;2381 1676;1332695;3715 1678;3918 2179;4061 2370;3780 2212;3676 2578;4029 2838;4263 2931;3429 1908;3507 2367;3394 2643;34393201;2935 3240;3140 3550;2545 2357;2778 2826;2370 2975]。

(1)初始化种群数目为NP=200,最大遗传迭代数目为G=1000,染色体基因个数为N=31,即城市数目。

(2)产生初始种群,计算个体适应度值,即路径长度;采用基于概率的方式选择进行操作的个体;对选中的成对个体,随机交叉所选中的成对城市坐标,以确保交叉后路径每个城市只到访一次;对选中的单个个体,随机交换其一对城市坐标作为变异操作,产生新的种群,进行下一次遗传操作。

(3)判断是否满足终止条件:若满足,则结束搜索过程,输出优化值;若不满足,则继续进行迭代优化。

Matlab代码如下:

%遗传算法解决TSP问题
clear 
close all; 
clc;   
C=[1304 2312;3639 1315;4177 2244;3712 1399;3488 1535;3326 1556;...
    3238 1229;4196 1044;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 2376;...
    3394 2643;3439 3201;2935 3240;3140 3550;2545 2357;2778 2826;...
    2370 2975];%省会城市坐标
N=size(C,1);%C的行数,即城市数目
D=zeros(N);%N*N的零矩阵,初始化任意两个城市距离间隔矩阵
%求任意两个城市距离间隔矩阵
for i=1:N
    for j=1:N
        D(i,j)=((C(i,1)-C(j,1))^2+(C(i,2)-C(j,2))^2)^0.5;
    end
end
NP=200;%种群数目
G=1000;%最大遗传迭代数
f=zeros(NP,N);%NP*N的零矩阵,用于存储种群
F=[];%种群更新中间存储
for i=1:NP
    f(i,:)=randperm(N);%1~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)=(1-((len(i,1)-minlen)/(maxlen-minlen+0.001)));
    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,:);%保持种群规模为n
    end
    f=F;%更新种群
    f(1,:)=R;%保留每代最优个体
    clear 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('适应度进化曲线')

运行结果如下:

 

 

2.4、遗传算法求解背包问题

[0-1背包问题]。有N件物品和一个容量为V的背包。第i件物品的体积是c(i),价值是w(i)。求解将哪些物品放入背包可使物品的体积总和不超过背包的容量,且价值总和最大。假设物品数量为10,背包的容量为300。每件物品的体积为[95,75,23,73,50,22,6,57,89,98],价值为[89,59,19,43,100,72,44,16,7,64]。

(1)初始化种群数目为Np =50,染色体基因维数为L=10,最大进化代数为G=100。

(2)产生二进制初始种群,其中1表示选择该物品,0表示不选择该物品。取适应度值为选择物品的价值总和,计算个体适应度值,当物品体积总和大于背包容量时,对适应度值进行惩罚计算。

(3)对适应度进行归一化,采用基于轮盘赌的选择操作、基于概率的交叉和变异操作,产生新的种群,并把历代的最优个体保留在新种群中,进行下一步遗传操作。

(4)判断是否满足终止条件:若满足,则结束搜索过程,输出优化值;若不满足,则继续进行迭代优化。
 

matlab代码如下:

%遗传算法解决0-1背包问题
clear  
close all;
clc; 
NP = 50;%种群规模
L = 10;%物品件数
Pc = 0.8;%交叉率
Pm = 0.05;%变异率
G = 100;%最大遗传代数
V = 300;%背包容量
C = [95,75,23,73,50,22,6,57,89,98]; %物品体积
W = [89,59,19,43,100,72,44,16,7,64];%物品价值
afa = 2; %惩罚函数系数
f = randi([0,1],NP,L);%随机获得初始种群
maxFit = 0 ;
%遗传算法循环部分
for k = 1:G
    %适应度计算,即计算总价值
    for i = 1:NP
         Fit(i) = func4(f(i,:),C,W,V,afa);
    end
    maxFit = max(Fit);%最大价值
    minFit = min(Fit);%最小价值
    rr = find(Fit==maxFit);
    fBest = f(rr(1,1),:);%历代最优个体
    Fit = (Fit - minFit)/(maxFit - minFit);%归一化适应度值
    %基于轮盘赌的选择
    sum_Fit = sum(Fit); %求适应度和
    fitvalue = Fit./sum_Fit;%求被选中的概率
    fitvalue = cumsum(fitvalue);%累加
    ms = sort(rand(NP,1)); %随机生成的概率,并按照由小到大排序
    fiti = 1;
    newi = 1;
    while newi <= NP
        if (ms(newi)) < fitvalue(fiti) %被选中的概率大于随机生成的
            nf(newi,:) = f(fiti,:); %选择复制
            newi = newi + 1;
        else
            fiti = fiti + 1;
        end
    end
    %基于概率的交叉操作
    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
    %基于概率的变异操作
    for m = 1:NP
        for n = 1:L
            r = rand(1,1);
            if r < Pm
                nf(m,n) = ~nf(m,n);
            end
        end
    end
    f = nf;
    f(1,:) = fBest; %保留最优个体在新种群中
    trace(k) = maxFit; %历代最优适应度
end
disp('最优个体如下:') ;
disp(fBest) ;
disp('最大价值如下:') ;
disp(maxFit) ;
figure
plot(trace)
xlabel('迭代次数')
ylabel('目标函数值')
title('适应度进化曲线')

适应度函数的代码如下:

%适应度函数,求物品价值总和
function result = func4(f,C,W,V,afa)
fit = sum(f.*W); %物品价值总和
TotalSize = sum(f.*C); %物品总体积
if TotalSize <= V %物品总体积小于背包容量
    fit = fit;
else %物品总体积大于背包容量
    fit = fit - afa * (TotalSize - V);
end
result = fit;
end

运行结果如下:其实10个物品,1表示选择该物品,0表示不选择该物品,最后的最大总价值为388

 

  • 10
    点赞
  • 74
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

nuist__NJUPT

给个鼓励吧,谢谢你

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值