优化算法一直都是数学建模比赛的热门题型,很多问题都可以简化为规划问题,利用启发式算法算法进行解答,所以学习优化问题的优先级和性价比还是很高的,基本都是掌握两三种启发式算法就可以解决大部分问题,启发式算法包括模拟退火算法、遗传算法、粒子群算法、蚁群算法等等,之前已经讲过模拟退火和遗传算法,这里再讲粒子群算法就结束了,后面的启发式算法就不再出了。
模拟退火:
遗传算法:
1995年,美国学者Kennedy和Eberhart共同提出了粒子群算法,其基本思想源于对鸟类群体行为进行建模与仿真的研究结果的启发。它的核心思想是利用群体中的个体对信息的共享使整个群体的运动在问题求解空间中产生从无序到有序的演化过程,从而获得问题的可行解。
直观一点的解释其实就是模拟鸟群觅食,利用鸟类觅食的群体行为和个人习惯搜索离食物更近的地方。
粒子群算法有一些假设
鸟类觅食受到群体行为和个人习惯两个东西的影响:
(1)离食物近的鸟类会给其他的同类传递信息,我这里离食物比较近,大家都快过来,那么所有鸟类都会有一个被吸引过去的趋势。
(2)鸟类有自己本身的经验,他自己之前也寻找过食物,所以会有一个倾向,根据经验走出下一步。
(3)鸟类飞行会有一个惯性,所以走下一步的时候会延惯性飞行。
以上三个就是鸟类飞行的重点,根据以上的鸟群觅食行为,开发了粒子群算法。
根据以上思想引入基本概念:
符号 | 粒子群含义 | 实际问题 含义 |
---|---|---|
x x x | 粒子 | 优化问题的解 |
f ( x ) f(x) f(x) | 适应度 | 评价解的优劣,规划问题中的目标函数 |
p d b e s t i d pdbest^d_i pdbestid | 第d次迭代第i个最佳位置 | 单个粒子目前为止找到的最佳位置 |
g d b e s t d gdbest^d gdbestd | 第d次迭代群体最佳位置 | 粒子群目前为止找到的最佳位置 |
v i d v_i^d vid | 第d次迭代,第i个粒子的速度 | 离下一个解的距离 |
n n n | 粒子个数 | 解的个数 |
w w w | 粒子的惯性权重 | 无 |
c 1 c_1 c1 | 粒子的个体学习因子 | 无 |
c 2 c_2 c2 | 粒子的社会学习因子 | 无 |
x x x | 位置 | 粒子(解)所在的坐标 |
注:x可以表示粒子同时也表示粒子的位置,两者是不矛盾的
当个鸟(粒子)第d步的速度 =自我认知部分 +社会认知部分+上一步自身的速度惯性
v ( 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 ) v(d) = w*v_i^{d‐1} + c_1*r_1*(pbest^d_i‐x^d_i) + c_2*r_2*(gbest^d‐x^d_i) v(d)=w∗vid‐1+c1∗r1∗(pbestid‐xid)+c2∗r2∗(gbestd‐xid)
其中 r 1 r_1 r1, r 2 r_2 r2是[0,1]上的随机数,由公式表达式可以知道,鸟的速度可以由三个部分的矢量和组成,符合鸟群的习惯和认知。
这只鸟第d+1步所在的位置 = 第d步所在的位置 + 第d步的速度 * 运动的时间
x i d + 1 + x i d + v i d x_i^{d+1}+x_i^d+v_i^d xid+1+xid+vid
核心参数的设置一般都是参考其他论文的参数设置,一般大家都会有一个默认的参数设置,这是不断实验出来的结果。
惯性权重一般取0.9,也有其他情况取0.9‐1.2的,没有具体的限制,也有的学者提出将惯性权重设置为自适应惯性权重、随机惯性权重。
学习因子分为个体学习因子和社会学习因子,一般情况都取2比较合适。学习因子也有改进的地方,但是一般都不会改进得太复杂,新手只要学到这里就可以了,后续改进可以自己去了解。
当鸟类已经找到食物后,再继续寻找食物只会浪费计算时间,那么我们就需要设定一个特定的条件,使得计算时,在达到条件后能够自动退出迭代。
(1)达到最大迭代次数退出循环
(2)达到鸟群达到的最优值长时间保持不变退出循环
那么退出循环就会有以上两种方式,最优值的长时间不变编程的思路可以如下
1.初始化计数器、最优值迭代忍受值。
2.定义适应度的容忍度
3.比较适应度的变化值和适应度的容忍度大小,如果前者小,则计数器加1;否则计数器清0。
4.判断计数器有没有超过“最优值迭代忍受值”,计数器的值超过了最优值迭代忍受值,那么我们
就跳出迭代循环,循环结束,鸟类停止觅食。
Matlab代码如下(示例):
题目我们以
y = 11 s i n x + 7 c o s 5 x y=11sin\ x+7cos\ 5x y=11sin x+7cos 5x
作为例题,区间定义在[-10,10]
clc,clear
%% 粒子群算法中的预设参数(参数的设置不是固定的,可以适当修改)
D = 500; % 迭代的次数
n = 10; % 粒子数量
factor = 1; % 变量个数
c1 = 2; % 个体学习因子
c2 = 2; % 社会学习因子
w = 0.9; % 惯性权重
D = 50; % 迭代的次数
vmax = 1.2; % 粒子的最大速度
x_lb = -10; % x的下界
x_ub = 10; % x的上界
x = zeros(n,factor);
for i = 1: factor % 将粒子群随机在定义域内
x(:,i) = x_lb(i) + (x_ub(i)-x_lb(i))*rand(n,1);
end
v = -vmax + 2*vmax .* rand(n,factor); % 随机初始化粒子的速度(这里我们设置为[-vmax,vmax])
f = zeros(n,1);
for i = 1:n % 循环整个粒子群,计算每一个粒子的适应度
f(i) = fun1(x(i,:)); % fun1为计算适应度的函数,
end
pbest = x; % 单个粒子迄今为止找到的最佳位置
gbest = pbest(find(f == min(f))); % 定义所有粒子迄今为止找到的最佳位置
fmean = zeros(1,D); %粒子群迭代平均适应度
fbest = zeros(1,D); %粒子群迭代的最优适应度
js = 0;
r = 20;
g = fun1(gbest); %当前最优值
%% 开始迭代()
for i = 1:D
x1 = x + v; %更新位置
v1 = w.*v + c1*rand()*(pbest-x) + c1*rand()*(gbest-x); %更新速度
for j=1:n %判断位置有没有超过取值区间,超过了取值区间就修改为区间最值
if x1(j,1) < x_lb
x(j,1) = x_lb;
elseif x1(j,1) > x_ub
x(j,1) = x_ub;
else
x(j,1) = x1(j,1);
end
%判断速度有没有超过最大值,超过了就修改为最大值
if v1(j,1) > vmax
v(j,1) = vmax;
else
v(j,1) = v1(j,1);
end
f(j,1) = fun1(x(j,1));
if f(j,1) < fun1(pbest(j,1))
pbest(j,1) = x(j,1);
if f(j,1) < fun1(gbest)
gbest = x(j,1);
end
end
end
f = fun1(x);
fmean(1,i) = mean(fun1(x)); %记录每次迭代平均适应度
fbest(1,i) = fun1(gbest); %记录每次迭代的最优适应度
%自动退出迭代循环
if fun1(gbest) - g < 0.0000001
js = js + 1;
end
g = fun1(gbest); %更新最优值的退出值
if js > r
break
end
end
xd=1:i;
plot(xd,fmean(1,1:i))
hold on
plot(xd,fbest(1,1:i))
xlabel('迭代次数')
legend('粒子群平均适应度','粒子群最优适应度')
disp('最佳的位置是:');
disp(gbest)
disp('此时最优值是:');
disp(-fun1(gbest)) %加负号是因为有设定适应度的时候就是设定为越小越好
function y = fun1(x)
y = 11*sin(x) + 7*cos(5*x);
% y = -(11*sin(x) + 7*cos(5*x)); % 如果调用fmincon函数,则需要添加负号改为求最小值
end
以上就是今天要讲的内容,本文仅仅简单介绍了粒子群的使用,而粒子群的方法还有更多的,包括多元函数的求最值,各自寻优算法都是可以应用的,不同之处在于解的产生,这也是大部分寻优算法的不同之处(有些算法的产生新解可以共通,大家以后题做多了就会遇到),寻优算法的相同之处在于都是基于继承之前的信息,通过多次迭代寻找最优值,本质并没有很大区别,学会两三种即可。