编程语言
首页 > 编程语言> > MATLAB实现智能计算方法实验:实验七 遗传算法

MATLAB实现智能计算方法实验:实验七 遗传算法

作者:互联网

资源链接

MATLAB实现智能计算方法课程所有实验代码资源链接为:MATLAB实现智能计算方法课程所有实验代码资源

实验目的

  1. 通过本次实验,进一步理解遗传算法的计算过程;
  2. 掌握手工计算过程和编码,并能够解决实际问题;
  3. 掌握MATLAB工具箱gatool的使用,并学会参数调整方法,解决实际优化问题。

实验内容

  1. 利用遗传算法,解决下列函数优化求解:

    { min ⁡ F ( x , y ) = ( x − 3.5 ) 2 + ( y + 4 ) 2 1 < x , y < 10 \left\{ \begin{array}{l} \min F(x,y) = {(x - 3.5)^2} + {(y + 4)^2}\\ 1 < x,y < 10 \end{array} \right. {minF(x,y)=(x−3.5)2+(y+4)21<x,y<10​

  2. 利用遗传算法,求函数 f ( x ) = x + 10 sin ⁡ ( 5 x ) + 7 cos ⁡ ( 4 x ) f(x) = x + 10\sin (5x) + 7\cos (4x) f(x)=x+10sin(5x)+7cos(4x) 的最大值,其中 0 ≤ x ≤ 9 {\rm{0}} \le x \le 9 0≤x≤9 。

实验步骤

1. 函数优化

1. 保存求解函数

将要求解的函数保存到工作空间中,代码如下:

function z = f1(x)
a = (x(1) - 3.5).^2;
b = (x(2) + 4).^2;
z = a + b;

2. 遗传算法工具箱优化求解

利用遗传算法工具箱进行优化求解,相关参数设置如下图1.1,options中plot function选择best fitness。

图1.1 相关参数设置

图1.1 相关参数设置

单击Start开始求解,求解过程中best fitness变化如下图1.2,最优解的值及此时变量取值如下图1.3。

图1.2 best fitness变化

图1.2 best fitness变化

图1.3 求解结果

图1.3 求解结果

由图1.3可知,最优解为25.0003,变量x的取值为3.484,y的取值为1,易知x=3.5, y=1时取到最优解为25,所求结果接近目标结果,效果较好。

3. 手工编码实现遗传算法

串位数、最大迭代次数等基本属性代码如下:

bn = 22;
inn = 50; %初始种群大小
gnmax = 500;  %最大代数
pc = 0.75; %交叉概率
pm = 0.05; %变异概率

选择、变异、交叉等基本函数的编码如下:

%根据变异概率判断是否变异
function pcc = pro(pc)
test(1: 100) = 0;
l = round(100*pc);
test(1: l) = 1;
n = round(rand*99) + 1;
pcc = test(n);   
end

%“选择”操作
function seln = sel(s, p)
inn = size(p, 1);
%从种群中选择两个个体,最好不要两次选择同一个个体
for i = 1: 2
   r = rand;  %产生一个随机数
   prand = p - r;
   j = 1;
   while prand(j) < 0
       j = j + 1;
   end
   seln(i) = j; %选中个体的序号
   if i == 2 && j == seln(i - 1)    %%若相同就再选一次
       r = rand;  %产生一个随机数
       prand = p - r;
       j = 1;
       while prand(j) < 0
           j = j + 1;
       end
   end
end
end

%“交叉”操作
function scro = cro(s, seln, pc)
[~, bn] = size(s);
pcc = pro(pc);  %根据交叉概率决定是否进行交叉操作,1则是,0则否
scro(1, :) = s(seln(1), :);
scro(2, :) = s(seln(2), :);
if pcc == 1
    chb = round(rand*(bn - 2)) + 1;  %在[1,bn-1]范围内随机产生一个交叉位
    scro(1, :) = [s(seln(1), 1: chb) s(seln(2), chb + 1: bn)];
    scro(2, :) = [s(seln(2), 1: chb) s(seln(1), chb + 1: bn)];
end
end

%“变异”操作
function snnew = mut(snew, pm)
r = size(snew);
bn = r(2);
snnew = snew;
pmm = pro(pm);  %根据变异概率决定是否进行变异操作,1则是,0则否
if pmm == 1
    chb = round(rand*(bn - 1)) + 1;  %在[1,bn]范围内随机产生一个变异位
    snnew(chb) = abs(snew(chb) - 1);
end
end

计算所有种群的适应度的函数如下:

%计算所有种群的适应度
function [f, p] = objf(s, a)
r = size(s);  %读取种群大小
inn = r(1);
bn = r(2);
for i = 1: inn
    x = bin2dec(num2str(s(i, :))); %将二进制转换为十进制
    xx = 1 + 9*x/(power(2, bn)-1); %转化为[0,9]区间的实数
    if(a == 1)
        f(i) = ft1(xx);
        f(i) = f(i);
    else
        f(i) = ft2(xx);
        f(i) = f(i);
    end
end
f = f'; %取距离倒数
%根据个体的适应度计算其被选择的概率
fsum = 0;
for i = 1: inn
   fsum = fsum + f(i)*f(i);% 让适应度越好的个体被选择概率越高
end
for i = 1: inn
   ps(i) = f(i)*f(i)/fsum;
end
%计算累积概率
p(1) = ps(1);
for i = 2: inn
   p(i) = p(i-1) + ps(i);
end
p = p';
end

将所求函数分为两个适应度函数,分别求解最小值,最后计算二者的和从而得到所求函数的最小值,代码如下:

%适应度函数1
function y1 = ft1(x1)
y1 = 42.25 - (x1 - 3.5).^2;
end

%适应度函数2
function y2 = ft2(x2)
y2 = 196 - (x2 + 4).^2;
end

求解器函数及绘图曲线函数代码如下:

[ymax1, ymean1, xmax1, ~] = solver(1);
[ymax2, ymean2, xmax2, gn] = solver(2);
ymax = - (ymax1 + ymax2 - 42.25 - 196);
ymean = - (ymean1 + ymean2 - 42.25 - 196);
gn = gn - 1;
%绘制曲线
subplot(3, 1, 1);
plot(1: gn, [ymax; ymean]);
title('历代适应度变化', 'FontSize', 10);
legend('最大适应度', '平均适应度', 'Location', 'southeast');
string1 = ['最终适应度为', num2str(ymax(gn))];
subplot(3, 1, 2);
plot(1: gn, xmax1, 'r-');
legend('自变量x', 'Location', 'southeast');
string2 = ['最终自变量x为', num2str(xmax1(gn))];
subplot(3, 1, 3);
plot(1: gn, xmax2, 'g-');
legend('自变量y', 'Location', 'southeast');
string3 = ['最终自变量y为', num2str(xmax2(gn))];
gtext(string1);
gtext(string2);
gtext(string3);

%定义求解器
function [ymax, ymean, xmax, gn] = solver(a)
inn = 50; %初始种群大小
bn = 22;
gnmax = 500;  %最大代数
pc = 0.75; %交叉概率
pm = 0.05; %变异概率
gn = 1;
s = round(rand(inn, bn));
[f, p] = objf(s, a);
while gn < gnmax + 1
   for j = 1: 2: inn
      seln = sel(s, p);  %选择操作
      scro = cro(s, seln, pc);  %交叉操作
      scnew(j, :) = scro(1, :); 
      scnew(j + 1, :) = scro(2, :);
      smnew(j, :) = mut(scnew(j, :), pm); %变异操作
      smnew(j + 1, :) = mut(scnew(j + 1, :), pm);
   end
   s = smnew;  %产生了新的种群
   [f, p] = objf(s, a);  %计算新种群的适应度
   %记录当前代最好和平均的适应度
   [fmax, nmax] = max(f);
   fmean = mean(f);
   ymax(gn) = fmax;
   ymean(gn) = fmean;
   %记录当前代的最佳个体
   x = bin2dec(num2str(s(nmax, :)));
   xx1 = 1 + 9*x/(power(2, bn)-1);
   xmax(gn) = xx1;
   gn = gn + 1;
end
end
 smnew(j, :) = mut(scnew(j, :), pm); %变异操作
      smnew(j + 1, :) = mut(scnew(j + 1, :), pm);
   end
   s = smnew;  %产生了新的种群
   [f, p] = objf(s);  %计算新种群的适应度
   %记录当前代最好和平均的适应度
   [fmax, nmax] = max(f);
   fmean = mean(f);
   ymax(gn) = fmax;
   ymean(gn) = fmean;
   %记录当前代的最佳个体
   x = bin2dec(num2str(s(nmax, :)));
   xx = 9*x/(power(2, bn)-1);
   xmax(gn) = xx;
   gn = gn + 1;
end
gn = gn - 1;
%绘制曲线
subplot(2, 1, 1);
plot(1: gn, [ymax; ymean]);
title('历代适应度变化', 'FontSize', 10);
legend('最大适应度', '平均适应度', 'Location', 'southeast');
string1 = ['最终适应度为', num2str(ymax(gn))];
subplot(2, 1, 2);
plot(1: gn, xmax, 'r-');
legend('自变量', 'Location', 'southeast');
string2 = ['最终自变量为', num2str(xmax(gn))];
gtext(string1);
gtext(string2);

运行程序,最终结果如下图1.4。

图1.4 手工编码结果

图1.4 手工编码结果
由图1.4可知,最优解为25.3557,变量x的取值为3.4987,y的取值为1.0354。

2. 求解函数最大值

1. 保存求解函数

将要求解的函数保存到工作空间中,代码如下:

function y = f2(x)
y = -(x + 10*sin(5*x) + 7*cos(4*x));

2. 遗传算法工具箱求解

利用遗传算法工具箱进行优化求解,相关参数设置如下图2.1。

图2.1 相关参数设置

图2.1 相关参数设置
求解过程best fitness变化如图2.2,最优解的值及此时变量取值如图2.3。

图2.2 best fitness变化

图2.2 best fitness变化

图2.3 求解结果

图2.3 求解结果

由图2.3可知,x=7.779时, f ( x ) = − ( x + 10 s i n ( 5 x ) + 7 c o s ( 4 x ) ) f\left(x\right)=-(x+10sin{(}5x)+7cos{(}4x)) f(x)=−(x+10sin(5x)+7cos(4x))取到最小值为-23.7807,即 f ( x ) = x + 10 s i n ( 5 x ) + 7 c o s ( 4 x ) f\left(x\right)=x+10sin{(}5x)+7cos{(}4x) f(x)=x+10sin(5x)+7cos(4x)在x=7.779时取到最大值23.7807。

为进行结果的验证,我们绘制所求函数在[0, 9 ]区间的图像如下图2.4,

图2.4 函数图像

图2.4 函数图像
结合图2.4以及上述结果,发现所求结果接近目标值,遗传算法优化效果较好。

3. 手工编码实现遗传算法

定义适应度函数代码如下:

function y = ft(x)
y = x + 10*sin(5*x) + 7*cos(4*x);
end

计算种群适应度的函数代码如下:

%计算所有种群的适应度
function [f, p] = objf(s)
r = size(s);  %读取种群大小
inn = r(1);
bn = r(2);
for i = 1: inn
    x = bin2dec(num2str(s(i, :))); %将二进制转换为十进制
    xx = 9*x/(power(2, bn)-1); %转化为[0,9]区间的实数
    f(i) = ft(xx); %计算函数值,即适应度
end
f = f'; %取距离倒数
%根据个体的适应度计算其被选择的概率
fsum = 0;
for i = 1: inn
   fsum = fsum + f(i)*f(i);% 让适应度越好的个体被选择概率越高
end
for i = 1: inn
   ps(i) = f(i)*f(i)/fsum;
end
%计算累积概率
p(1) = ps(1);
for i = 2: inn
   p(i) = p(i-1) + ps(i);
end
p = p';
end

计算的主函数及绘图函数代码如下:

%产生初始种群
s = round(rand(inn, bn));
[f, p] = objf(s);
gn = 1;
while gn < gnmax + 1
   for j = 1: 2: inn
      seln = sel(s, p);  %选择操作
      scro = cro(s, seln, pc);  %交叉操作
      scnew(j, :) = scro(1, :); 
      scnew(j + 1, :) = scro(2, :);
      smnew(j, :) = mut(scnew(j, :), pm); %变异操作
      smnew(j + 1, :) = mut(scnew(j + 1, :), pm);
   end
   s = smnew;  %产生了新的种群
   [f, p] = objf(s);  %计算新种群的适应度
   %记录当前代最好和平均的适应度
   [fmax, nmax] = max(f);
   fmean = mean(f);
   ymax(gn) = fmax;
   ymean(gn) = fmean;
   %记录当前代的最佳个体
   x = bin2dec(num2str(s(nmax, :)));
   xx = 9*x/(power(2, bn)-1);
   xmax(gn) = xx;
   gn = gn + 1;
end
gn = gn - 1;
%绘制曲线
subplot(2, 1, 1);
plot(1: gn, [ymax; ymean]);
title('历代适应度变化', 'FontSize', 10);
legend('最大适应度', '平均适应度', 'Location', 'southeast');
string1 = ['最终适应度为', num2str(ymax(gn))];
subplot(2, 1, 2);
plot(1: gn, xmax, 'r-');
legend('自变量', 'Location', 'southeast');
string2 = ['最终自变量为', num2str(xmax(gn))];
gtext(string1);
gtext(string2);

运行程序,最终结果如下图2.5。

图2.5 手工编码结果

图2.5 手工编码结果
由图2.5可知,最优解为24.7839,变量x的取值为7.8766。

标签:seln,end,bn,inn,适应度,实验,MATLAB,gn,遗传算法
来源: https://blog.csdn.net/qq_36949278/article/details/122014034