粒子群算法笔记

介绍:

粒子群是智能算法的一种,也称为鸟群算法,简单来说就是鸟根据惯性、自身经验、社会经验三者调整自己的每一步路线,最后找到最优解的方法。说白了,粒子群算法的实质依然是蒙特卡洛,只不过稍微优化了一些,它的核心算法在下面:

 符号   含义  n  粒子个数  c 1  粒子的个体学习因子, 也称为个体加速因子  c 2  粒子的社会学习因子,也称为社会加速因子  w  速度的惯性权重  v i d  第d次迭代时,第i个粒子的速度  x i d  第d次迭代时,第i个粒子所在的位置  f ( x )  在位置x时的适应度值(一般取目标函数值)  p b e s t i d  到第d次迭代为止,第i个粒子经过的最好的位置  g b e s t d  到第d次迭代为止,所有粒子经过的最好的位置  \begin{array}{|c|c|} \hline \text { 符号 } & \text { 含义 } \\ \hline n & \text { 粒子个数 } \\ \hline c_{1} & \text { 粒子的个体学习因子, 也称为个体加速因子 } \\ \hline c_{2} & \text { 粒子的社会学习因子,也称为社会加速因子 } \\ \hline w & \text { 速度的惯性权重 } \\ \hline v_{i}^{d} & \text { 第d次迭代时,第i个粒子的速度 } \\ \hline x_{i}^{d} & \text { 第d次迭代时,第i个粒子所在的位置 } \\ \hline f(x) & \text { 在位置x时的适应度值(一般取目标函数值) } \\ \hline p b e s t_{i}^{d} & \text { 到第d次迭代为止,第i个粒子经过的最好的位置 } \\ \hline g b e s t^{d} & \text { 到第d次迭代为止,所有粒子经过的最好的位置 } \\ \hline \end{array}  符号 nc1c2wvidxidf(x)pbestidgbestd 含义  粒子个数  粒子的个体学习因子也称为个体加速因子  粒子的社会学习因子,也称为社会加速因子  速度的惯性权重  d次迭代时,第i个粒子的速度  d次迭代时,第i个粒子所在的位置  在位置x时的适应度值(一般取目标函数值 到第d次迭代为止,第i个粒子经过的最好的位置  到第d次迭代为止,所有粒子经过的最好的位置 

这只鸟第 d d d 步的速度 = = = 上一步自身的速度惯性 + + 自我认知部分 + + + 社会认知部分(每—步运动的时间 t t t —般取 1)

v i d = w v i d − 1 + c 1 r 1 ( p b e s t i d − x i d ) + c 2 r 2 ( g b e s t d − x i d ) \boldsymbol{v}_{i}^{d}=\boldsymbol{w} \boldsymbol{v}_{i}^{d-1}+\boldsymbol{c}_{1} \boldsymbol{r}_{1}\left(\boldsymbol{p} \boldsymbol{b} \boldsymbol{e} \boldsymbol{s} \boldsymbol{t}_{i}^{d}-\boldsymbol{x}_{i}^{d}\right)+\boldsymbol{c}_{2} \boldsymbol{r}_{2}\left(\boldsymbol{g} \boldsymbol{b} \boldsymbol{e} \boldsymbol{s} \boldsymbol{t}^{d}-\boldsymbol{x}_{i}^{d}\right) vid=wvid1+c1r1(pbestidxid)+c2r2(gbestdxid)

这只鸟第 d d d 步所在的位置 = = = d − 1 d-1 d1 步所在的位置 + + d − 1 d-1 d1 步的速度 ∗ * 运动的时间(三个部分的和)

x i d + 1 = x i d + v i d \boldsymbol{x}_{i}^{\boldsymbol{d}+\mathbf{1}}=\boldsymbol{x}_{i}^{\boldsymbol{d}}+\boldsymbol{v}_{\boldsymbol{i}}^{d} xid+1=xid+vid

【流程图】
在这里插入图片描述
粒子群算法的作用:主要是求解函数的最值,但也可以用于求解方程组、多元函数的拟合、拟合微分方程。不过后面三个属于粒子群的进阶应用了,我打算放在文章最后

改进:

一、惯性权重

① 线性递减惯性权重

解析:惯性权重随着迭代次数减少,有利于先搜索全局再搜索局部最优解

w 1 d = w start − ( w start − w end ) × d K w^{d}_1=w_{\text {start}}-\left(w_{\text {start}}-w_{\text {end}}\right) \times \frac{d}{K} w1d=wstart(wstartwend)×Kd

其中 d d d 是当前迭代的次数, K K K 是迭代总次数, w start w_{\text {start}} wstart 一般取 0.9, w end w_{\text {end}} wend一般取 0.4

② 非线性递减惯性权重

解析:原理与上一个相似,只不过惯性权重是非线性递减的

w 2 d = w start − ( w start − w end ) × ( d K ) 2 w^{d}_2=w_{\text {start}}-\left(w_{\text {start}}-w_{\text {end}}\right) \times\left(\frac{d}{K}\right)^{2} w2d=wstart(wstartwend)×(Kd)2

w 3 d = w start − ( w start − w end ) × [ 2 d K − ( d K ) 2 ] w^{d}_3=w_{\text {start}}-\left(w_{\text {start}}-w_{\text {end}}\right) \times\left[\frac{2 d}{K}-\left(\frac{d}{K}\right)^{2}\right] w3d=wstart(wstartwend)×[K2d(Kd)2]

【线性递减与非线性递减图示】

③ 自适应惯性权重(以求最小值为例)

解析:适应度越小,说明距离最优解越近,此时更需要局部搜索,即需要一个较小的惯性权重;反之,适应度越大,说明距离最优解越远,此时更需要全局搜索,即需要一个较大的惯性权重

w i d = { w min ⁡ + ( w max ⁡ − w min ⁡ ) f ( x i d ) − f min ⁡ d f average d − f min ⁡ d , f ( x i d ) ≤ f average d w max ⁡ , f ( x i d ) > f average d w_{i}^{d}=\left\{\begin{array}{c} w_{\min }+\left(w_{\max }-w_{\min }\right) \frac{f\left(x_{i}^{d}\right)-f_{\min }^{d}}{f_{\text {average}}^{d}-f_{\min }^{d}}, \quad f\left(x_{i}^{d}\right) \leq f_{\text {average}}^{d} \\ w_{\max } \quad, f\left(x_{i}^{d}\right)>f_{\text {average}}^{d} \end{array}\right. wid={wmin+(wmaxwmin)faveragedfmindf(xid)fmind,f(xid)faveragedwmax,f(xid)>faveraged

其中:

w start w_{\text {start}} wstart 一般也取 0.9, w end w_{\text {end}} wend一般也取 0.4

f average d = ∑ i = 1 f ( x i d ) / n f_{\text {average}}^{d}=\sum_{i=1} f\left(x_{i}^{d}\right) / n faveraged=i=1f(xid)/n ,即第 d d d 次迭代时所有粒子的平均适应度

f min ⁡ d = min ⁡ { f ( x 1 d ) , f ( x 2 d ) , ⋯   , f ( x n d ) } f_{\min }^{d}=\min \left\{f\left(x_{1}^{d}\right), f\left(x_{2}^{d}\right), \cdots, f\left(x_{n}^{d}\right)\right\} fmind=min{f(x1d),f(x2d),,f(xnd)},即第 d d d 次迭代时所有粒子的最小适应度

④ 随机惯性权重

解析:可以避免在迭代前期局部搜索能力的不足,也可以避免在迭代后期全局搜索能力的不足

ω = μ min ⁡ + ( μ max ⁡ − μ min ⁡ ) × rand ⁡ ( ) + σ × randn ⁡ ( ) \omega=\mu_{\min }+\left(\mu_{\max }-\mu_{\min }\right) \times \operatorname{rand}()+\sigma \times \operatorname{randn}() ω=μmin+(μmaxμmin)×rand()+σ×randn()

其中:

μ min ⁡ \mu_{\min } μmin是随机惯性权重的最小值, μ max ⁡ \mu_{\max } μmax是随机惯性权重的最大值

r a n d ( ) rand() rand()为 [0,1] 均匀分布随机数, r a n d n ( ) randn() randn()为正态分布的随机数

σ \sigma σ (方差) 用来度量随机变量权重 ω \omega ω 与其数学期望之间的偏离程度,使实验误差服从正态分布

二、学习因子

① 压缩因子

解析:可确保粒子群算法的收敛性,并可取消对速度的边界限制

c 1 = c 2 = 2.05 , C = c 1 + c 2 = 4.1 , c 1=c 2=2.05, C=c 1+c 2=4.1, c1=c2=2.05,C=c1+c2=4.1, 收缩因子 Φ = 2 ∣ ( 2 − C − C 2 − 4 C ) ∣ \boldsymbol{\Phi}=\frac{\mathbf{2}}{\left|\left(\mathbf{2}-\boldsymbol{C}-\sqrt{\boldsymbol{C}^{2}-4 \boldsymbol{C}}\right)\right|} Φ=(2CC24C )2

速度更新的公式改为:

v i d = Φ × [ w v i d − 1 + c 1 r 1 ( p b e s t i d − x i d ) + c 2 r 2 ( g b e s t d − x i d ) ] \boldsymbol{v}_{i}^{d}=\boldsymbol{\Phi} \times\left[\boldsymbol{w} \boldsymbol{v}_{i}^{d-1}+\boldsymbol{c}_{1} \boldsymbol{r}_{1}\left(\boldsymbol{p} \boldsymbol{b} \boldsymbol{e} \boldsymbol{s} \boldsymbol{t}_{i}^{d}-\boldsymbol{x}_{i}^{d}\right)+\boldsymbol{c}_{2} \boldsymbol{r}_{2}\left(\boldsymbol{g} \boldsymbol{b} \boldsymbol{e} \boldsymbol{s} \boldsymbol{t}^{d}-\boldsymbol{x}_{i}^{d}\right)\right] vid=Φ×[wvid1+c1r1(pbestidxid)+c2r2(gbestdxid)]

② 非对称学习因子

解析:在算法搜索初期采用较大的 c 1 c_1 c1 值和较小的 c 2 c_2 c2 值,使粒子尽量发散到搜索空间,增加全局搜索的能力。随着迭代次数的增加,使 c 1 c_1 c1 线性递减, c 2 c_2 c2 线性递增,从而加强了粒子向全局最优点的收敛能力,也就是局部搜索的能力

c 1 i n i = 2.5 , c 1 f i n = 0.5 , c 2 i n i = 1 , c 2 f i n = 2.25 c 1 d = c 1 i n i + ( c 1 f i n − c 1 i n i ) × d K ; c 2 d = c 2 i n i + ( c 2 f i n − c 2 i n i ) × d K \begin{aligned} c_{1}^{i n i}=2.5, c_{1}^{f i n} &=0.5, c_{2}^{i n i}=1, c_{2}^{f i n}=2.25 \\ c_{1}^{d}=c_{1}^{i n i}+\left(c_{1}^{f i n}-c_{1}^{i n i}\right) & \times \frac{d}{K} ; c_{2}^{d}=c_{2}^{i n i}+\left(c_{2}^{f i n}-c_{2}^{i n i}\right) \times \frac{d}{K} \end{aligned} c1ini=2.5,c1finc1d=c1ini+(c1finc1ini)=0.5,c2ini=1,c2fin=2.25×Kd;c2d=c2ini+(c2finc2ini)×Kd

实践:

在这里插入图片描述
我选择使用自适应惯性权重收缩因子做为改进的粒子群算法,并使用 M A T L A B MATLAB MATLAB 自带粒子群算法进行验算

(PS:代码不作讲解,毕竟这不是教学,只是笔记罢了)

【代码部分】

M A T L A B MATLAB MATLAB 自带粒子群算法函数代码:

code.m

close all
clear;clc
narvs = 2; % 变量个数
x_lb = [-3 4.1]; % x的下界(长度等于变量的个数,每个变量对应一个下界约束)
x_ub = [12.1 5.8]; % x的上界

tic
options = optimoptions('particleswarm','FunctionTolerance',1e-12,'MaxStallIterations',50,'MaxIterations',20000,'HybridFcn',@fmincon,'PlotFcn','pswplotbestf');
title('Best Function Value: -38.8503','Interpreter','none');
[x,fval] = particleswarm(@Obj_fun,narvs,x_lb,x_ub,options);
fval = -fval
toc

% 最优值:38.7328

Obj_fun.m

function y = Obj_fun(x)  
    y = -(21.5 + x(1)*sin(4*pi*x(1)) + x(2)*sin(20*pi*x(2)));
end

【结果图】
在这里插入图片描述

自适应惯性权重收缩因子优化粒子群算法函数:

realcode.m

close all
clear;clc
n = 50; % 粒子数量
narvs = 2; % 变量个数
c1 = 2;  % 每个粒子的个体学习因子,也称为个体加速常数
c2 = 2;  % 每个粒子的社会学习因子,也称为社会加速常数
C = c1 + c2; % 因子之和
w_min = 0.4;  % 最小惯性权重
w_max = 0.9;  % 最小惯性权重
fai = 2/(2-C-(C^2-4*C)^0.5); % 收缩因子
K = 500;  % 迭代的次数
vmax = 1.2; % 粒子的最大速度
x_lb = [-3 4.1]; % x的下界(长度等于变量的个数,每个变量对应一个下界约束)
x_ub = [12.1 5.8]; % x的上界

for i = 1: narvs
    x(:,i) = x_lb(i) + (x_ub(i)-x_lb(i))*rand(n,1);    % 随机初始化粒子所在的位置在定义域内
end
v = -vmax + 2*vmax .* rand(n,narvs);  % 随机初始化粒子的速度(这里我们设置为[-vmax,vmax]%% 计算适应度
fit = zeros(n,1);  % 初始化这n个粒子的适应度全为0
for i = 1:n  % 循环整个粒子群,计算每一个粒子的适应度
    fit(i) = Obj_fun_2(x(i,:));   % 调用Obj_fun_2函数来计算适应度
end 
pbest = x;   % 初始化这n个粒子迄今为止找到的最佳位置(是一个n*narvs的向量)
ind = find(fit == max(fit), 1);  % 找到适应度最大的那个粒子的下标
gbest = x(ind,:);  % 定义所有粒子迄今为止找到的最佳位置(是一个1*narvs的向量)

%% 函数图像
ezsurf(@(x,y)(21.5 + x.*sin(4.*pi.*x) + y.*sin(20.*pi.*y)),[-10 10 -10 10]); % 以x和y代替x1和x2
hold on;

%% 在图上标上这n个粒子的位置用于演示
h = scatter3(x(:,1),x(:,2),fit,'*r');  % scatter3是绘制三维散点图的函数(这里返回h是为了得到图形的句柄,未来我们对其位置进行更新)

%% 迭代K次来更新速度与位置
fitnessbest = ones(K,1);  % 初始化每次迭代得到的最佳的适应度
for d = 1:K  % 开始迭代,一共迭代K次
    for i = 1:n   % 依次更新第i个粒子的速度与位置 % 自适应惯性权重
        f_i = fit(i);  % 取出第i个粒子的适应度
        f_avg = sum(fit)/n;  % 计算此时适应度的平均值
        f_max = max(fit); % 计算此时适应度的最大值
        if f_i >= f_avg
             if f_avg ~= f_max  % 如果分母为0,我们就干脆令w=w_min
                w = w_min + (w_max - w_min)*(f_max - f_i)/(f_max - f_avg);
            else
                w = w_min;
             end
        else
            w = w_max;
        end
        v(i,:) = fai * (w*v(i,:) + c1*rand(1)*(pbest(i,:) - x(i,:)) + c2*rand(1)*(gbest - x(i,:)));  % 更新第i个粒子的速度
        x(i,:) = x(i,:) + v(i,:); % 更新第i个粒子的位置
        % 如果粒子的位置超出了定义域,就对其进行调整
        for j = 1: narvs
            if x(i,j) < x_lb(j)
                x(i,j) = x_lb(j);
            elseif x(i,j) > x_ub(j)
                x(i,j) = x_ub(j);
            end
        end
        fit(i) = Obj_fun_2(x(i,:));  % 重新计算第i个粒子的适应度
        if fit(i) > Obj_fun_2(pbest(i,:))   % 如果第i个粒子的适应度大于这个粒子迄今为止找到的最佳位置对应的适应度
           pbest(i,:) = x(i,:);   % 那就更新第i个粒子迄今为止找到的最佳位置
        end
        if  fit(i) > Obj_fun_2(gbest)  % 如果第i个粒子的适应度大于所有的粒子迄今为止找到的最佳位置对应的适应度
            gbest = pbest(i,:);   % 那就更新所有粒子迄今为止找到的最佳位置
        end
    end
    fitnessbest(d) = Obj_fun_2(gbest);  % 更新第d次迭代得到的最佳的适应度
    pause(0.1)  % 暂停0.1s
    h.XData = x(:,1);  % 更新散点图句柄的x轴的数据(此时粒子的位置在图上发生了变化)
    h.YData = x(:,2);   % 更新散点图句柄的y轴的数据(此时粒子的位置在图上发生了变化)
    h.ZData = fit;  % 更新散点图句柄的z轴的数据(此时粒子的位置在图上发生了变化)
end

figure(2) 
plot(fitnessbest)  % 绘制出每次迭代最佳适应度的变化图
xlabel('迭代次数');
disp('最佳的位置是:'); disp(gbest)
disp('此时最优值是:'); disp(Obj_fun_2(gbest))

% 最优值:38.6247

Obj_fun_2.m

function y = Obj_fun_2(x)
    y = 21.5 + x(1)*sin(4*pi*x(1)) + x(2)*sin(20*pi*x(2));
end

【动态图】
在这里插入图片描述
【结果图】
在这里插入图片描述
在这里插入图片描述

进阶:

上面讲了粒子群求解函数最值问题,现在针对求解方程组、多元函数的拟合、拟合微分方程进行实践分析

一、求解方程组

在这里插入图片描述

这里可以使用三个方法进行求解方程组,vpasolve 函数、fsolve 函数和粒子群,前面两个方法需要指定初始值和搜索范围,而粒子群只用指定搜索范围,相比起来会更加简单。注意,粒子群和两个函数使用的方程组函数不一样(具体看下面代码)

【代码部分】

main.m

%% vpasolve 函数

clear; clc
syms x1 x2 x3
eqn =  [abs(x1+x2)-abs(x3)  == 0, x1*x2*x3+18 == 0, x1^2*x2+3*x3 == 0]
% [x1, x2, x3] = vpasolve(eqn, [x1, x2, x3], [0 0 0])  % 这个初始值不行
[x1, x2, x3] = vpasolve(eqn, [x1, x2, x3], [1 1 1])  % 换一个初始值试试

% x = 6.80305735323491        -0.414133803887221          6.38892354934769
% SSE:0


%% fsolve 函数

x0 = [0,0,0];  % 初始值
x = fsolve(@my_fun,x0)
% 换一个初始值试试
x0 = [1,1,1];  % 初始值
format long g  % 显示更多的小数位数
x = fsolve(@my_fun,x0)

% x = 6.80305735323491        -0.414133803887221          6.38892354934769
% SSE:7.105427357601e-15


%% 粒子群算法(尝试多次,找到最优解)

clear; clc
narvs = 3;
% 使用粒子群算法,不需要指定初始值,只需要给定一个搜索的范围
lb = -10*ones(1,3);  ub = 10*ones(1,3);  
options = optimoptions('particleswarm','FunctionTolerance',1e-12,'MaxStallIterations',100,'MaxIterations',20000,'SwarmSize',100);
[x, fval] = particleswarm(@Obj_fun,narvs,lb,ub,options) 

% x = 1.42058091501338         -4.34008181244093          2.91950089742755
% SSE:2.22044604925031e-15

my_fun.m(vpasolve 函数、fsolve 函数)

function F = my_fun(x)
    F(1) =  abs(x(1)+x(2))-abs(x(3));
    F(2) =  x(1) * x(2) * x(3) + 18;
    F(3) = x(1)^2*x(2)+3*x(3);
end

Obj_fun.m(粒子群)

function f = Obj_fun(x)
    f1= abs(x(1)+x(2))-abs(x(3)) ;
    f2 = x(1) * x(2) * x(3) + 18;
    f3= x(1)^2 * x(2) + 3*x(3);
    f = abs(f1) + abs(f2) + abs(f3);
end

S S E SSE SSE是残差平方和,但为了图个方便,虽然使用这个名称,但运算的公式是abs(f1) + abs(f2) + abs(f3),也就是 Obj_fun.m 中的最后一步,表示算法整体的误差值,当然越小越好,从最后结果来看显然是 vpasolve 函数的运算效果最好,因为它的 S S E SSE SSE 是 0,而粒子群的 S S E SSE SSE 也很小,在可接受范围内。因此选择哪个还得看具体模型环境,从简便和准确性之间权衡

二、多元函数的拟合

在这里插入图片描述
之所以不用 M A T L A B MATLAB MATLAB c f t o o l cftool cftool拟合工具箱是因为它仅有 x y z xyz xyz 三元的函数拟合,当遇到多维拟合时,就可以用到粒子群了,但前提是知道它的拟合函数

【代码部分】

code.m

clear; clc
global x y;  % 将x和y定义为全局变量(方便在子函数中直接调用,要先声明)
load data_x_y  % 数据集内里面有x和y两个变量
narvs = 2;
% 使用粒子群算法,不需要指定初始值,只需要给定一个搜索的范围
lb = [-10 -10];  ub = [10 10];  
[k, fval] = particleswarm(@Obj_fun,narvs,lb,ub) 

% k = -0.0915    0.3169
% SSE:297.0634


% 使用粒子群算法后再利用fmincon函数混合求解
options = optimoptions('particleswarm','HybridFcn',@fmincon);
[k,fval] = particleswarm(@Obj_fun,narvs,lb,ub,options)

% k = -0.0915    0.3169
% SSE:297.0634

Obj_fun.m

function f = Obj_fun(k)
    global x y;  % 在子函数中使用全局变量前也需要声明下
    y_hat = exp(-k(1)*x(:,1)) .* sin(k(2)*x(:,2)) + x(:,3).^2;
    f = sum((y - y_hat) .^ 2);
end

从上面结果看出粒子群混合求解的方法和原方法的效果差不多

三、拟合微分方程

在这里插入图片描述
【求解方法】
在这里插入图片描述
在这里插入图片描述
现在的未知量: β 1 、 β 2 、 a 、 b \beta_1、\beta_2、a、b β1β2ab

【代码部分】

main.m

clear;clc
load mydata.mat  % 导入数据(共三列,分别是S,I,R的数量)
global true_s true_i true_r  n  % 定义全局变量
n = size(mydata,1);  % 一共有多少行数据
true_s = mydata(:,1);
true_i = mydata(:,2);
true_r = mydata(:,3);
figure(1)
plot(1:n,true_i,'b-',1:n,true_r,'g-') % 单独画出I和R的数量
legend('I','R')

% 粒子群算法来求解
% beta1,beta2,a,b
% 给定参数的搜索范围(根据题目来给),后期可缩小范围
lb = [0 0 -1 -1]; 
ub = [1 1 1 1];  
% lb = [0 0 -0.2 -0.2]; 
% ub = [0.3 0.3 0.2 0.2];  
options = optimoptions('particleswarm','Display','iter','SwarmSize',200);
[h, fval] = particleswarm(@Obj_fun, 4, lb, ub, options)  % h就是要优化的参数,fval是目标函数值, 第二个输入参数4代表我们有4个变量需要搜索

beta1 = h(1);  % t<=15时,易感染者与已感染者接触且被传染的强度
beta2 = h(2);  % t>15时,易感染者与已感染者接触且被传染的强度
a = h(3); % 康复率gamma = a+bt
b = h(4);  % 康复率gamma = a+bt
[t,p]=ode45(@(t,x) SIR_fun(t,x,beta1,beta2,a,b), [1:n],[true_s(1) true_i(1) true_r(1)]);   
p = round(p);  % 对p进行四舍五入(人数为整数)

figure(3)  % 真实的人数和拟合的人数放到一起看看
plot(1:n,true_i,'b-',1:n,true_r,'g-') 
hold on
plot(1:n,p(:,2),'b--',1:n,p(:,3),'g--') 
legend('I','R','拟合的I','拟合的R')

% 预测未来的趋势
N = 27; % 计算N天
[t,p]=ode45(@(t,x) SIR_fun(t,x,beta1,beta2,a,b), [1:N],[true_s(1) true_i(1) true_r(1)]);   
p = round(p);  % 对p进行四舍五入(人数为整数)
figure(4)
plot(1:n,true_i,'b-',1:n,true_r,'g-') 
hold on
plot(1:N,p(:,2),'b--',1:N,p(:,3),'g--') 
legend('I','R','拟合的I','拟合的R')

% beta1 = 0.2227
% beta2 = 0.1326
% a = 0.0488
% b = -0.0012
% SSE:157

SIR_fun.m

function dx=SIR_fun(t,x,beta1,beta2,a,b)  
    % beta1 : t<=15时,易感染者与已感染者接触且被传染的强度
    % beta2   : t>15时,易感染者与已感染者接触且被传染的强度
    % a  : 康复率gamma = a+bt
    % b  : 康复率gamma = a+bt
    if t <=15
        beta = beta1;
    else
        beta = beta2;
    end
    gamma = a + b * t;  
    dx = zeros(3,1);  % x(1)表示S  x(2)表示I  x(3)表示R
    C = x(1)+x(2);  % 传染病系统中的有效人群,也就是课件中的N' = S+I
    dx(1) = - beta*x(1)*x(2)/C;  
    dx(2) = beta*x(1)*x(2)/C - gamma*x(2);
    dx(3) = gamma*x(2); 
end

Obj_fun.m

function f = Obj_fun(h)  
    % 注意,h就是我们要估计的目标函数里面的参数
    % h的长度就是我们待估参数的个数
    global true_s  true_i  true_r n   % 在子函数中使用全局变量前也需要声明下
    beta1 = h(1);  % t<=15时,易感染者与已感染者接触且被传染的强度
    beta2 = h(2);  % t>15时,易感染者与已感染者接触且被传染的强度
    a = h(3); % 康复率gamma = a+bt
    b = h(4);  % 康复率gamma = a+bt
    [t,p]=ode45(@(t,x) SIR_fun(t,x,beta1,beta2,a,b) , [1:n],[true_s(1) true_i(1) true_r(1)]);   
    p = round(p);  % 对p进行四舍五入(人数为整数)
    % p的第一列是易感染者S的数量,p的第二列是患者I的数量,p的第三列是康复者R的数量
    f = sum((true_s - p(:,1)).^2  + (true_i -  p(:,2)).^2  + (true_r - p(:,3)).^2);
end

【结果图】
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

总结:

粒子群作为一个智能算法,在解决模型的运算方面有很强大的功能(无论是简洁性还是效率),但是仅此而已,真正建模最重要的还是模型的建立,前面也提及了,在有特定约束或方程组的条件下可以用粒子群求解,但若连公式都没有谈何解题,因此粒子群只是作为辅佐而存在的,论模型的建立还得阅读大量文献和教材

  • 5
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
本框架提供了有关粒子群算法(PSO)和遗传算法(GA)的完整实现,以及一套关于改进、应用、测试、结果输出的完整框架。 本框架对粒子群算法与遗传算法进行逻辑解耦,对其中的改进点予以封装,进行模块化,使用者可以采取自己对该模块的改进替换默认实现组成新的改进算法与已有算法进行对比试验。试验结果基于Excel文件输出,并可通过设定不同的迭代结束方式选择试验数据的输出方式,包括: 1. 输出随迭代次数变化的平均达优率数据(设定终止条件区间大于0)。 2. 输出随迭代次数变化的平均最优值数据(设定终止条件区间等于0)。 本框架了包含了常用基准函数的实现以及遗传算法粒子群算法对其的求解方案实现和对比,如TSP,01背包,Banana函数,Griewank函数等。并提供大量工具方法,如KMeans,随机序列生成与无效序列修补方法等等。 对遗传算法的二进制编码,整数编码,实数编码,整数序列编码(用于求解TSP等),粒子群算法的各种拓扑结构,以及两种算法的参数各种更新方式均有实现,并提供接口供使用者实现新的改进方式并整合入框架进行试验。 其中还包括对PSO进行离散化的支持接口,和自己的设计一种离散PSO方法及其用以求解01背包问题的实现样例。 欢迎参考并提出宝贵意见,特别欢迎愿意协同更新修补代码的朋友(邮箱starffly@foxmail.com)。 代码已作为lakeast项目托管在Google Code: http://code.google.com/p/lakeast http://code.google.com/p/lakeast/downloads/list 某些类的功能说明: org.lakest.common中: BoundaryType定义了一个枚举,表示变量超出约束范围时为恢复到约束范围所采用的处理方式,分别是NONE(不处理),WRAP(加减若干整数个区间长度),BOUNCE(超出部分向区间内部折叠),STICK(取超出方向的最大限定值)。 Constraint定义了一个代表变量约束范围的类。 Functions定义了一系列基准函数的具体实现以供其他类统一调用。 InitializeException定义了一个代表程序初始化出现错误的异常类。 Randoms类的各个静态方法用以产生各种类型的随机数以及随机序列的快速产生。 Range类的实现了用以判断变量是否超出约束范围以及将超出约束范围的变量根据一定原则修补到约束范围的方法。 ToStringBuffer是一个将数组转换为其字符串表示的类。 org.lakeast.ga.skeleton中: AbstractChromosome定义了染色体的公共方法。 AbstractDomain是定义问题域有关的计算与参数的抽象类。 AbstractFactorGenerator定义产生交叉概率和变异概率的共同方法。 BinaryChromosome是采用二进制编码的染色体的具体实现类。 ConstantFactorGenerator是一个把交叉概率和变异概率定义为常量的参数产生器。 ConstraintSet用于在计算过程中保存和获取应用问题的各个维度的约束。 Domain是遗传算法求解中所有问题域必须实现的接口。 EncodingType是一个表明染色体编码类型的枚举,包括BINARY(二进制),REAL(实数),INTEGER(整型)。 Factor是交叉概率和变异概率的封装。 IFactorGenerator参数产生器的公共接口。 Population定义了染色体种群的行为,包括种群的迭代,轮盘赌选择和交叉以及最优个体的保存。 org.lakeast.ga.chromosome中: BinaryChromosome二进制编码染色体实现。 IntegerChromosome整数编码染色体实现。 RealChromosome实数编码染色体实现。 SequenceIntegerChromosome整数序列染色体实现。 org.lakeast.pso.skeleton中: AbstractDomain提供一个接口,将粒子的位置向量解释到离散空间,同时不干扰粒子的更新方式。 AbstractFactorGenerator是PSO中参数产生器的公共抽象类。 AbstractParticle定义了PSO种群中粒子的基本行为,最主要是实现了如何根据现有位置计算得到下一代粒子的位置的合法值。 ConstraintSet用于在粒子迭代过程中保存和获取应用问题的各个维度的约束。 AbstractSwarm.java各种拓扑结构的PSO种群的抽象父类,主要实现了种群迭代过程中计算流程的定义以及中间数据被如何输出到测试工具类。 Domain是PSO算法求解中所有问题域必须实现的接口。 DynamicFatorGenerator若种群在迭代过程中,w,c1,c2随迭代次数发生变化,那么它们的产生器需要继承这个抽象类。 Factor封装了w,c1,c2三个参数的字面值。 Location用于保存和获取迭代中粒子的位置和速度向量的数值。 NeighborhoodBestParticle定义了采用邻域版本的PSO算法的具体实现。主要是实现了如何根据邻域版本的PSO算法计算下一迭代中的粒子速度。 RingTopoSwarm定义环拓扑结构的具体实现,主要是定义了如何获取粒子的邻域粒子的方法。 StaticTopoSwarm静态拓扑结构的PSO算法的抽象父类。 org.lakeast.pso.swarm中包含粒子群拓扑结构的各种实现,基本见名知意。 对各种问题的求解样例位于org.lakeast.main包中,以...TaskTest结尾,基本见名知意。 以ShafferF6DomainTaskTes对ShafferF6函数进行求解(采用的是PSO,遗传算法样例参见TSPValueTaskTest)为例说明求解过程如下: 1. 入口函数位于org.lakeast.main.ShafferF6DomainTaskTest中,go函数执行。 2. 在go函数中,首先指定迭代次数(numberOfIterations),测试多少轮(testCount,多次运行以得到平均达优值),种群大小(popSize),邻域大小(neighborhoodSize),迭代结束条件(exitCondition,由于制定了迭代次数,所以设定为[0,0],也就是只有达到指定迭代次数才退出)。 3. 以testCount,numberOfIterations以及迭代结束条件exitCondition为参数构建TestBatch类的实例batch。这个类用来进行管理参与测试的各种具体算法,且把数据结果按指定的格式输出为Excel文件。 4. 指定PSO中的因子产生方法,采用ExponentFactorGenerator和ConstrictFactorGenerator两种方式(实现位于org.lakeast.pso.gen包)。 5. Y表示参与测试的算法数目。 6. Testable是所有可以被TestBatch测试的类需要实现的接口,以提供TestBatch生成结果Excel文件所需要的数据。 7. Domain接口是所有可以被算法解决的问题所需要实现的接口,比如说明该问题所需要的粒子位置约束范围,速度约束范围,以及适值评估的公司等。这里的Domain被实例化为ShafferF6Domain,也就是按照ShafferF6函数评估适值。 8. RingTopoSwarm是用来封装环拓扑邻域结构的类,NeighboordBestParticle是配合该类来实现按邻域最优更新速度而不是全局最优来更新。 9. 各个测试算法都被加入到TestBatch以后,batch.run()开始执行算法比较过程并输出结果Excel文件到C盘根目录(输出路径可在Testable接口中配置,除了生成Excel文件外,还可以通过修改log4j.properties在制定的位置产生运行结果日志)。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值