粒子群算法的实现

  1. 基本概念:

鸟群中有个体和群体,个体和群体的信息是可以互通的。个体在随机搜寻食物的过程中,只要跟踪离食物最近的群体,就能最有效地找到食物。

(1)粒子:优化问题的候选解,指鸟群中的独立个体;

(2)位置:候选解所在的位置,即鸟群个体的位置;

(3)速度:粒子的移动速度;

(4)适应度:评价粒子优劣的值,一般为优化目标函数的数值;

(5)个体极值:单个粒子迄今为止找到的最佳位置;

(6)群体极值:所有粒子迄今为止找到的最佳位置。

2.基本流程

(1)初始粒子;

(2)计算适应度值;

(在实际问题的解决中,构建目标函数是最重要的,也是最难的。)

(3)定义初始个体极值与群体极值;

(4)更新粒子位置与速度;(最经典的部分)

粒子群算法python迭代图 粒子群 python_matlab

(5)更新个体极值和群体极值。

粒子群算法python迭代图 粒子群 python_开发语言_02

3、函数代码实现

(1)主函数:

(POSmain.m)

clear
 clc

%绘制原图        图1目标函数的三维网格图

x1=-15:1:15;
 x2=-15:1:15;
 [x1,x2]=meshgrid(x1,x2);
 y=x1.^2+x2.^2-x1.*x2-10.*x1-4.*x2+60;
 mesh(x1,x2,y);    
 hold on;

%%预设参数

n=100; %粒子群的规模
 d=2; %变量个数
 c1=2;
 c2=2;
 w=0.9;%权重一般设为0.9
 K=50; %迭代次数

%%分布粒子的取值范围及速度的取值范围

x=-10+20*rand(n,d);  %产生一个n*d的随机矩阵,x中元素取值在[-10,10]中
 v=-5+10*rand(n,d);   %产生一个n*d的随机矩阵,v中元素取值在[-5,5]中

%%计算适应度

fit=zeros(n,1);%创建一个n*1全为零的矩阵,实现每个个体适应度的初始化
 for j=1:n
     fit(j)=fun(x(j,:));%x(j,:)代表了一个个体的位置。
 endpbest=x;%初始化每个个体的最好位置。
 ind=find(min(fit)==fit);%find找到非零数的下标,此为找到最小适应度对应的下标。
 gbest=x(ind,:);%初始化全体个体中的最好位置
 %h=scatter3(x(:,1),x(:,2),fit,'o');  %图2 粒子的初始分布图,MATLAB三维散点图的绘制。

%%更新速度与位置

for i=1:K
     for j=1:n %每一个个体都得更新。
        v(j,:)=w*v(j,:) + c1*rand*(pbest(j,:)-x(j,:)) + c2*rand*(gbest-x(j,:));%rand是[0,1]随机数,速度更新公式
        
        v(j,find(v(j,:)<-5))=-5;%这里发现速度小于-5时取-5
        v(j,find(v(j,:)>5))=5;%这里发现速度大于5时取5
        
        x(j,:)=x(j,:)+0.5*v(j,:);%位置更新公式
        x(j,find(x(j,:)<-10))=-10;%这里发现位置小于-10时取-10
        x(j,find(x(j,:)>10))=10;%这里发现位置大于10时取10
        
        %重新计算适应度
        fit(j)=fun(x(j,:));
        if x(j,:)<fun(pbest(j,:))
            pbest(j,:)=x(j,:);
        end
        if fun(pbest(j,:))<fun(gbest)
            gbest=pbest(j,:);
        end
     end
     fitnessbest(i)=fun(gbest);
     pause(0.01);    %为了直观,每更新一次,暂停0.01秒
     h.XData=x(:,1);
     h.YData=x(:,2);
     h.ZData=fit;
 end
  h=scatter3(x(:,1),x(:,2),fit,'o');  %图2 粒子的初始分布图,MATLAB三维散点图的绘制。
 hold on;
 figure(2)
 plot(fitnessbest);
 xlabel('迭代次数');

2、 目标函数:

 (fun.m)

function y=fun(x)
y=2*x(1)^2+x(2)^2-x(1)*x(2)-10*x(1)-4*x(2)+60;

粒子群算法python迭代图 粒子群 python_开发语言_03

(1)最后一次迭代的种群的图像

 

粒子群算法python迭代图 粒子群 python_粒子群算法python迭代图_04

(2)迭代与适应度值的图像

4.python实现,适应度函数为f ( x , y ) = x^2 + y^2 + x ,求解f(x,y)的最小值点.

代码:

# 速度
# Vi+1 = w*Vi + c1 * r1 * (pbest_i - Xi) + c2 * r2 * (gbest_i - Xi)
# 位置
# Xi+1 = Xi + Vi+1
# vi, xi 分别表示粒子第i维的速度和位置
# pbest_i, gbest_i 分别表示某个粒子最好位置第i维的值、整个种群最好位置第i维的值

import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl

mpl.rcParams['font.sans-serif'] = ['SimHei']  # 指定默认字体
mpl.rcParams['axes.unicode_minus'] = False  # 解决保存图像是负号'-'显示为方块的问题

def fitness_func(X):
    """计算粒子的的适应度值,也就是目标函数值,X 的维度是 size * 2 """
    A = 10
    pi = np.pi
    x = X[:, 0]
    y = X[:, 1]
    return x**2+y**2+x

#更新速度

def velocity_update(V, X, pbest, gbest, c1, c2, w, max_val):
    """
    根据速度更新公式更新每个粒子的速度,有20个体,维度为2。
    :param V: 粒子当前的速度矩阵,20*2 的矩阵
    :param X: 粒子当前的位置矩阵,20*2 的矩阵
    :param pbest: 每个粒子历史最优位置,20*2 的矩阵
    :param gbest: 种群历史最优位置,1*2 的矩阵
    """
    size = X.shape[0]
    r1 = np.random.random((size, 1))
    r2 = np.random.random((size, 1))
    V = w*V+c1*r1*(pbest-X)+c2*r2*(gbest-X)
    # 防止越界处理
    V[V < -max_val] = -max_val
    V[V > max_val] = max_val
    return V

#更新粒子位置

def position_update(X, V):
    """
    根据公式更新粒子的位置
    :param X: 粒子当前的位置矩阵,维度是 20*2
    :param V: 粒子当前的速度举着,维度是 20*2
    """
    return X+V

#粒子群算法的主要流程

def pos():
    w = 1
    c1 = 2
    c2 = 2
    r1 = None
    r2 = None
    dim = 2
    size = 20
    iter_num = 1000 #迭代参数
    max_val = 0.5
    best_fitness = float(9e10)#初始化最优适应度值
    fitness_val_list = []#初始化适应度值
    # 初始化种群各个粒子的位置
    X = np.random.uniform(-5, 5, size=(size, dim))
    # 初始化各个粒子的速度
    V = np.random.uniform(-0.5, 0.5, size=(size, dim))
    # print(X)
    p_fitness = fitness_func(X)#初始化的个体的最优适应值
    g_fitness = p_fitness.min()#初始化全体个体的最优适应值
    fitness_val_list.append(g_fitness)

    # 初始化的个体最优位置和种群最优位置
    pbest = X
    gbest = X[p_fitness.argmin()]
    # 迭代计算
    for i in range(1, iter_num):
        V = velocity_update(V, X, pbest, gbest, c1, c2, w, max_val)
        X = position_update(X, V)
        p_fitness2 = fitness_func(X)
        g_fitness2 = p_fitness2.min()

        # 更新每个粒子的历史最优位置
        for j in range(size):
            if p_fitness[j] > p_fitness2[j]:
                pbest[j] = X[j]
                p_fitness[j] = p_fitness2[j]
            # 更新群体的最优位置
            if g_fitness > g_fitness2:
                gbest = X[p_fitness2.argmin()]
                g_fitness = g_fitness2
            # 记录最优迭代记录
            fitness_val_list.append(g_fitness)
            i += 1

    # 输出迭代结果
    print("最优值是:%.5f" % fitness_val_list[-1])
    print("最优解是:x=%.5f,y=%.5f" % (gbest[0], gbest[1]))

    # 绘图
    plt.plot(fitness_val_list, color='r')
    plt.title('迭代过程')
    plt.show()

pos()

运行结果:

粒子群算法python迭代图 粒子群 python_开发语言_05