例子种群算法

1. 概念

    粒子群优化算法(PSO:Particle swarm optimization) 是一种进化计算技术(evolutionary computation)。

    源于对鸟群捕食的行为研究。粒子群优化算法的基本思想:是通过群体中个体之间的协作和信息共享来寻找最优解.

    PSO的优势:在于简单容易实现并且没有许多参数的调节。目前已被广泛应用于函数优化、神经网络训练、模糊系统控制以及其他遗传算法的应用领域。 

2. 算法

 

2.1 问题抽象

      鸟被抽象为没有质量和体积的微粒(点),并延伸到N维空间,粒子i在N维空间的位置表示为矢量Xi=(x1,x2,…,xN),飞行速度表示为矢量Vi=(v1,v2,…,vN)。每个粒子都有一个由目标函数决定的适应值(fitness value),并且知道自己到目前为止发现的最好位置(pbest)和现在的位置Xi。这个可以看作是粒子自己的飞行经验。除此之外,每个粒子还知道到目前为止整个群体中所有粒子发现的最好位置(gbest)(gbest是pbest中的最好值),这个可以看作是粒子同伴的经验。粒子就是通过自己的经验和同伴中最好的经验来决定下一步的运动。 

 

2.2 更新规则

      PSO初始化为一群随机粒子(随机解)。然后通过迭代找到最优解。在每一次的迭代中,粒子通过跟踪两个“极值”(pbest,gbest)来更新自己。在找到这两个最优值后,粒子通过下面的公式来更新自己的速度和位置。

     

      公式(1)的第一部分称为【记忆项】,表示上次速度大小和方向的影响;公式(1)的第二部分称为【自身认知项】,是从当前点指向粒子自身最好点的一个矢量,表示粒子的动作来源于自己经验的部分;公式(1)的第三部分称为【群体认知项】,是一个从当前点指向种群最好点的矢量,反映了粒子间的协同合作和知识共享。粒子就是通过自己的经验和同伴中最好的经验来决定下一步的运动。

     以上面两个公式为基础,形成了PSO的标准形式。

     

     公式(2)和 公式(3)被视为标准PSO算法。

3.算法 C++实现

/***
 *  计算y=-x(x-1)的最大值
 *  取值范围x--[-2,2]
 * @author BreezeDust
 *
 */
public class PSOTest {
    int n=2; //粒子个数,这里为了方便演示,我们只取两个,观察其运动方向
    double[] y;
    double[] x;
    double[] v;
    double c1=2;
    double c2=2;
    double pbest[];
    double gbest;
    double vmax=0.1;
    public void fitnessFunction(){//适应函数
        for(int i=0;i<n;i++){
            y[i]=-1*x[i]*(x[i]-2);
        }
    }
    public void init(){ //初始化
        x=new double[n];
        v=new double[n];
        y=new double[n];
        pbest=new double[n];
        /***
         * 本来是应该随机产生的,为了方便演示,我这里手动随机落两个点,分别落在最大值两边
         */
        x[0]=-0.5;
        x[1]=2.6;
        v[0]=0.01;
        v[1]=0.02;
        fitnessFunction();
        //初始化当前个体极值,并找到群体极值
        for(int i=0;i<n;i++){
            pbest[i]=y[i];
            if(y[i]>gbest) gbest=y[i];
        }
        System.out.println("start gbest:"+gbest);
    }
    public double getMAX(double a,double b){
        return a>b?a:b;
    }
    //粒子群算法
    public void PSO(int max){
        for(int i=0;i<max;i++){
            double w=0.4;
            for(int j=0;j<n;j++){
                //更新位置和速度
                v[j]=w*v[j]+c1*Math.random()*(pbest[j]-x[j])+c2*Math.random()*(gbest-x[j]);
                if(v[j]>vmax) v[j]=vmax;
                x[j]+=v[j];
                //越界判断
                if(x[j]>2) x[j]=2;
                if(x[j]<-2) x[j]=-2;
                
            }
            fitnessFunction();
            //更新个体极值和群体极值
            for(int j=0;j<n;j++){
                pbest[j]=getMAX(y[j],pbest[j]);
                if(pbest[j]>gbest) gbest=pbest[j];
                System.out.println(x[j]+"  "+v[j]);
            }
            System.out.println("======"+(i+1)+"======gbest:"+gbest);
        }
        
        
    }
    public static void main(String[] args){
        PSOTest ts=new PSOTest();
        ts.init();
        ts.PSO(100);
    }
}

输出结果

start gbest:0.0
-0.4  0.1
0.0  -10.751668729351186
======1======gbest:0.0
-0.6822365786740794  -0.2822365786740793
0.0  -5.375834364675593
======2======gbest:0.0
-0.5822365786740794  0.1
0.0  -2.6879171823377965
======3======gbest:0.0
-0.48223657867407943  0.1
-1.3439585911688983  -1.3439585911688983
======4======gbest:0.0
-0.38223657867407945  0.1
-1.2439585911688982  0.1
======5======gbest:0.0
-0.47659030560462123  -0.09435372693054181
-1.143958591168898  0.1
======6======gbest:0.0
-0.37659030560462126  0.1
-1.043958591168898  0.1
======7======gbest:0.0
-0.2765903056046213  0.1
-0.943958591168898  0.1
======8======gbest:0.0
-0.27903394174424034  -0.0024436361396190653
-0.843958591168898  0.1
======9======gbest:0.0
-0.38899022876058803  -0.10995628701634769
-0.7439585911688981  0.1
======10======gbest:0.0
-0.35250959144436234  0.03648063731622572
-0.6439585911688981  0.1
======11======gbest:0.0
........
........
........
........
0.9999990975760489  -1.556071309835406E-6
======98======gbest:1.0
1.0000000029937202  4.411275849326098E-9
1.0000001827158205  1.085139771533034E-6
======99======gbest:1.0
0.9999999993730952  -3.6206249540206964E-9
1.0000001197322141  -6.298360633295484E-8
======100======gbest:1.0

结果分析

我们可以从打印的数据看出来,刚开始x[0]和x[1]分散在最大值两边,然后x[0]和x[1]逐渐聚集到1的周围,这里,我们已经收敛到x=1这个地方了,这正是我们要求的最大值,其最大值为1,下面是图解过程。

    1.初始状态

    2.第二次x[1]向左边移动了

   3.最后,两点聚集在1上,上面多个圈是他们聚集的过程,可以看出来,聚集过程是个越来越密集的过程。

转载原文链接1:https://blog.youkuaiyun.com/qq_34504481/article/details/79763824

转载原文链接2:http://www.cnblogs.com/BreezeDust/p/3354769.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值