白话例子群算法—C语言实现

简介
    上次在自话遗传算法中提到后期会写两篇关于粒子群算法和蚁群算法的博文,所以这次给大家带来的是我对粒子群的一些理解,并附带一个相当简单的实例去描述这个算法,我会尽力通俗易懂的把整个算法描述一遍,其实粒子群算法的思想也挺简单的,希望我不要反而写复杂了,下面同样引用百度百科的摘要结束简介部分。
    粒子群优化算法(PSO)是一种进化计算技术(evolutionary computation),1995 年由Eberhart 博士和kennedy 博士提出,源于对鸟群捕食的行为研究 。该算法最初是受到飞鸟集群活动的规律性启发,进而利用群体智能建立的一个简化模型。粒子群算法在对动物集群活动行为观察基础上,利用群体中的个体对信息的共享使整个群体的运动在问题求解空间中产生从无序到有序的演化过程,从而获得最优解。
基本思想
    正如简介所描述的那样,粒子群算法是模拟群体智能所建立起来的一种优化算法,像后面我向大家介绍的蚁群算法也属于这类算法,粒子群算法可以用鸟类在一个空间内随机觅食为例,所有的鸟都不知道食物具体在哪里,但是他们知道大概距离多远,最简单有效的方法就是搜寻目前离食物最近的鸟的周围区域。
    所以,粒子群算法就是把鸟看成一个个粒子,并且他们拥有位置和速度这两个属性,然后根据自身已经找到的离食物最近的解和参考整个共享于整个集群中找到的最近的解去改变自己的飞行方向,最后我们会发现,整个集群大致向同一个地方聚集。而这个地方是离食物最近的区域,条件好的话就会找到食物。这就是粒子群算法,很好理解。
算法描述
    所以,我们需要一个pbest来记录个体搜索到的最优解,用gbest来记录整个群体在一次迭代中搜索到的最优解。速度和粒子位置的更新公式如下:
    v[i] = w * v[i] + c1 * rand() * (pbest[i] – present[i]) + c2 * rand() * (gbest – present[i])    
    present[i] = present[i] + v[i]                                                                                                          
    其中v[i]代表第i个粒子的速度,w代表惯性权值,c1和c2表示学习参数,rand()表示在0-1之间的随机数,pbest[i]代表第i个粒子搜索到的最优值,gbest代表整个集群搜索到的最优值,present[i]代表第i个粒子的当前位置。
    我这里打了一个求解y=-x*(x-1) 在[-2,2]上最大值的粒子群算法,选用这个简单的例子主要是能让大家清楚的看到效果和粒子的运动方向,也方便理解我想说的一些观点。

代码如下

#include <iostream>  
#include <math.h>  
#include <cstdlib>  
#include <ctime>  
using namespace std;  
const int n=2;  
 class PSOTest
 {  
//  int n=2; //粒子个数,这里为了方便演示,我们只取两个,观察其运动方向  
    float* y;  
    float* x;  
    float* v;  
    float c1;  
    float c2;  
    float *pbest;  
    float gbest;  
    float vmax;  
 public:  
       
   void fitnessFunction()
	{
	   //适应函数  
        for(int i=0;i<n;i++)
		{  
            y[i]=-1*x[i]*(x[i]-1);  
        }  
    }  
     void init()
	 { //初始化  
        x=new float[n];  
        v=new float[n];  
        y=new float[n];  
        pbest=new float[n];  
        c1=2;  
        c2=2;  
        vmax=(float)0.1;  
        gbest=0;  
        /*** 
         * 本来是应该随机产生的,为了方便演示,我这里手动随机落两个点,分别落在最大值两边 
         */  
        x[0]=-0.5;  
        x[1]=(float)1.9;  
        v[0]=(float)0.01;  
        v[1]=(float)0.02;  
        fitnessFunction();  
        //初始化当前个体极值,并找到群体极值  
        for(int i=0;i<n;i++)
		{  
            pbest[i]=y[i];  
            if(y[i]>gbest) gbest=y[i];  
        }  
       
    }  
	  float Max(float a,float b)  
	  {  
		if(a>=b)  
			return a;  
		return b;  
	  }  
    //粒子群算法  
    void PSO(int max)
	{  
        float w;  
        for(int i=0;i<max;i++)
		{  
             
            for(int j=0;j<n;j++)
			{  
                //更新位置和速度  
                w=(float)((float)1.2-(float)(1.2-0.8)/max*i);  
                srand(time(NULL));  
                v[j]=w*v[j]+c1*((float)rand()/RAND_MAX)*(pbest[j]-x[j])+c2*((float)rand()/RAND_MAX)*(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 k=0;k<n;k++)
			{  
                pbest[k]=Max(y[k],pbest[k]);  
                if(pbest[k]>gbest) gbest=pbest[k];  
                cout<<x[k]<<"  "<<v[k]<<endl;  
            }  
            cout<<"  gbest   "<<gbest<<endl;  
        }        
    }  
 };
 
int main()
{  
    PSOTest * ts=new PSOTest();  
    ts->init();  
    ts->PSO(200);  
    return 0;  
}  

在实验时候,会出现极值很难收敛的问题,所以我们这里讲权重因子w线性的从1.2降到0.8,可以看到,比固定不变,收敛速度要好的很多。

注:本文系转载文章
转载出处:http://blog.csdn.net/lycommand/article/details/50755946?locationNum=5&fps=1

    原文作者:蚁群算法
    原文地址: https://blog.csdn.net/u010480899/article/details/53405787
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞