|
- /***********************************************************************************
- Particle.h - 粒子抽象基类头文件
- ************************************************************************************
- 类说明:
- 该类是单个粒子的一个抽象,是一个抽象基类;
- 派生类必须对该类中的成员变量进行内存分配;
- 该类包含计算粒子适应度的纯虚函数;
- 该类不能直接对象化,必须在其子类对适应度函数进行实现后方能对粒子进行实例化
- ************************************************************************************
- 作者:贾家磊,jiajialei816@163.com,中国地质大学(北京)地震勘探实验室,2011/11/30
- ************************************************************************************/
- #ifndef _PARTICLE_H_JIAJIALEI
- #define _PARTICLE_H_JIAJIALEI
- #include <stdlib.h>
- class CParticle
- {
- public:
- ////////////////////
- //构造与析构部分
- ////////////////////
- //粒子类缺省构造函数
- CParticle();
- //粒子类带参数构造函数
- CParticle(int dimension);
- //粒子类析构函数
- virtual ~CParticle();
- //////////////////
- //参数设置部分
- //////////////////
- //设置粒子的位置
- virtual void SetPosition(float *position);
- //设置粒子的速度
- virtual void SetVelocity(float *velocity);
- //设置粒子个体的最优解位置
- virtual void SetBestPosition(float *bestPosition);
- //设置粒子的适应度
- virtual void SetFitness(float fitness) { fFitness = fitness; };
- //设置粒子个体的最好适应度
- virtual void SetBestFitness(float bestFitness) { fBestFitness = bestFitness; };
- //设置粒子个体的维度
- virtual void SetDimension(int dimension) { nDimension = dimension; };
- //////////////////
- //参数输出部分
- //////////////////
- //返回粒子的位置
- virtual float* GetPosition() { return pfPosition; };
- //返回粒子的速度
- virtual float* GetVelocity() { return pfVelocity; };
- //返回粒子个体的最优解位置
- virtual float* GetBestPosition() { return pfBestPosition; }
- //返回粒子的适应度
- virtual float GetFitness() { return fFitness; }
- //返回粒子个体的最好适应度
- virtual float GetBestFitness() { return fBestFitness; };
- //返回粒子个体的维度
- virtual int GetDimension() { return nDimension; };
- //////////////
- //计算部分
- //////////////
- //更新粒子的最好适应度及其位置信息
- virtual void UpdateBestPosition();
- //计算粒子的适应度值,纯虚函数,必须在其子类定义
- virtual void CalculateFitness() = 0;
- protected:
- //粒子的位置(坐标)
- float *pfPosition;
- //粒子的速度
- float *pfVelocity;
- //粒子个体的最优解位置(坐标)
- float *pfBestPosition;
- //粒子的适应度(误差,其值越小适应度越好)
- float fFitness;
- //粒子个体的最好适应度(误差,其值越小适应度越好)
- float fBestFitness;
- //粒子的维度
- int nDimension;
- };
- #endif//_PARTICLE_H_JIAJIALEI
- /***********************************************************************************
- Particle.cpp - 粒子抽象基类的实现文件
- ************************************************************************************
- 类说明:
- 该类是单个粒子的一个抽象,是一个抽象基类;
- 该类包含计算粒子适应度的纯虚函数;
- 该类不能直接对象化,必须在其子类对适应度函数进行实现后方能对粒子进行实例化
- ************************************************************************************
- 作者:贾家磊,jiajialei816@163.com,中国地质大学(北京)地震勘探实验室,2011/11/30
- ************************************************************************************/
- #include "Particle.h"
- /*粒子类缺省构造函数*/
- CParticle::CParticle()
- {
- pfPosition = NULL;
- pfVelocity = NULL;
- pfBestPosition = NULL;
- fFitness = 0;
- fBestFitness = 0;
- nDimension = 0;
- }
- /*粒子类带参数构造函数*/
- CParticle::CParticle(int dimension)
- {
- pfPosition = NULL;
- pfVelocity = NULL;
- pfBestPosition = NULL;
- fFitness = 0;
- fBestFitness = 0;
- nDimension = dimension;
- }
- /*粒子类析构函数*/
- CParticle::~CParticle()
- {
- }
- /*更新粒子的最好适应度及其位置信息*/
- void CParticle::UpdateBestPosition()
- {
- //如果粒子当前计算的适应度小于粒子个体的最好适应度时
- if(fFitness<fBestFitness)
- {
- fBestFitness = fFitness;
- for(int i=0; i<nDimension; i++)
- pfBestPosition[i] = pfPosition[i];
- }
- }
- /*设置粒子的位置*/
- void CParticle::SetPosition(float *position)
- {
- for(int i=0; i<nDimension; i++)
- pfPosition[i] = position[i];
- }
- /*设置粒子个体的最优解位置*/
- void CParticle::SetBestPosition(float *bestPosition)
- {
- for(int i=0; i<nDimension; i++)
- pfBestPosition[i] = bestPosition[i];
- }
- /*设置粒子的速度*/
- void CParticle::SetVelocity(float *velocity)
- {
- for(int i=0; i<nDimension; i++)
- pfVelocity[i] = velocity[i];
- }
- /***********************************************************************************
- ParticleSwarm.cpp - 粒子群基类的实现文件
- ************************************************************************************
- 类说明:
- 该类是由多个抽象粒子组成的粒子群基类;
- 粒子群派生类必须对粒子群基类中的成员变量进行内存分配
- 该类主要包括粒子群随机初始化函数Randomize和粒子群进化一代函数ParticleFly
- ************************************************************************************
- 作者:贾家磊,jiajialei816@163.com,中国地质大学(北京)地震勘探实验室,2011/11/30
- ************************************************************************************/
- #include "ParticleSwarm.h"
- #include <time.h>
- /*粒子群类缺省构造函数*/
- CParticleSwarm::CParticleSwarm()
- {
- cParticle = NULL;
- pfMinPosition = NULL;
- pfMaxPosition = NULL;
- pfMaxVelocity = NULL;
- nParticleNum = 0;
- nGroupBestIndex = 0;
- fMomentum = 0.8f;
- fMinMomentum = 0.4f;
- fMaxMomentum = 0.9f;
- fC1 = 2.0f;
- fC2 = 2.0f;
- }
- /*粒子群类带参数构造函数*/
- CParticleSwarm::CParticleSwarm(int dimension, int particleNum)
- {
- pfMinPosition = NULL;
- pfMaxPosition = NULL;
- pfMaxVelocity = NULL;
- nParticleNum = particleNum;
- nGroupBestIndex = 0;
- fMomentum = 0.8f;
- fMinMomentum = 0.4f;
- fMaxMomentum = 0.9f;
- fC1 = 2.0f;
- fC2 = 2.0f;
- }
- /*粒子群类析构函数*/
- CParticleSwarm::~CParticleSwarm()
- {
- }
- /*设置粒子位置信息的下界*/
- void CParticleSwarm::SetMinPosition(float *minPosition)
- {
- int dimension = cParticle[0].GetDimension();
- for(int i=0; i<dimension; i++)
- pfMinPosition[i] = minPosition[i];
- }
- /*设置粒子位置信息的上界*/
- void CParticleSwarm::SetMaxPosition(float *maxPosition)
- {
- int dimension = cParticle[0].GetDimension();
- for(int i=0; i<dimension; i++)
- pfMaxPosition[i] = maxPosition[i];
- }
- /*设置粒子的最大速度*/
- void CParticleSwarm::SetMaxVelocity(float percent)
- {
- if(!nParticleNum) return;
- int dimension = cParticle[0].GetDimension();
- for(int i=0; i<dimension; i++)
- pfMaxVelocity[i] = percent*(pfMaxPosition[i]-pfMinPosition[i]);
- }
- void CParticleSwarm::SetMaxVelocity(float *maxVelocity)
- {
- int dimension = cParticle[0].GetDimension();
- for(int i=0; i<dimension; i++)
- pfMaxVelocity[i] = maxVelocity[i];
- }
- /*设置线性惯性权系数的范围*/
- void CParticleSwarm::SetMomentumRange(float minMomentum, float maxMomentum)
- {
- fMinMomentum = minMomentum;
- fMaxMomentum = maxMomentum;
- }
- /*跟新粒子群中全局最优粒子的索引号*/
- void CParticleSwarm::UpdateGroupBestIndex()
- {
- for(int i=0; i<nParticleNum; i++)
- {
- if(i!=nGroupBestIndex &&
- cParticle[i].GetBestFitness()<cParticle[nGroupBestIndex].GetBestFitness())
- nGroupBestIndex = i;
- }
- }
- /*返回粒子群中各个粒子最优位置的平均*/
- void CParticleSwarm::GetGroupAveragePosition(float* avgPosition)
- {
- int i,j;
- int dimension = cParticle[0].GetDimension();
- float *bestPos;
- for(i=0; i<dimension; i++)
- avgPosition[i] = 0.0;
- for(j=0; j<nParticleNum; j++)
- {
- bestPos = cParticle[j].GetBestPosition();
- for(i=0; i<dimension; i++)
- avgPosition[i] += bestPos[i];
- }
- for(i=0; i<dimension; i++)
- avgPosition[i] /= nParticleNum;
- }
- /*返回粒子群中各个粒子适应度的平均值*/
- float CParticleSwarm::GetGroupAverageFitness()
- {
- float avg = 0.0;
- for(int i=0; i<nParticleNum; i++)
- avg += cParticle[i].GetBestFitness();
- return (avg/nParticleNum);
- }
- /*返回粒子群中各个粒子最优适应度的中位索引号*/
- int CParticleSwarm::GetGroupMedianIndex()
- {
- int i,j,k,index;
- float temp;
- float *pfData = new float[nParticleNum];
- int* pIndex = new int[nParticleNum];
- for(i=0; i<nParticleNum; i++)
- {
- pfData[i] = cParticle[i].GetBestFitness();
- pIndex[i] = i;
- }
- for(i=0; i<=nParticleNum/2; i++)
- {
- k = nParticleNum-i;
- temp = pfData[0];
- index = 0;
- //寻找序列中最大值以及其索引号
- for(j=1; j<k; j++)
- {
- if(pfData[j]>temp)
- {
- temp = pfData[j];
- index = j;
- }
- }
- //将序列尾部的值写入到当前序列中最大值处
- pfData[index] = pfData[k-1];//将序列中的最大值逐个覆盖
- pIndex[index] = k-1;
- }
- //粒子群中各个粒子最优适应度的中位数
- index = pIndex[nParticleNum/2];
- delete []pfData;
- delete []pIndex;
- return index;
- }
- /*计算粒子群中各个粒子最优适应度的中位数,然后返回对应粒子的最优位置*/
- void CParticleSwarm::GetGroupMedianPosition(float* midPosition)
- {
- int i,j,k,index;
- float temp, *pos;
- float *pfData = new float[nParticleNum];
- int* pIndex = new int[nParticleNum];
- for(i=0; i<nParticleNum; i++)
- {
- pfData[i] = cParticle[i].GetBestFitness();
- pIndex[i] = i;
- }
- for(i=0; i<=nParticleNum/2; i++)
- {
- k = nParticleNum-i;
- temp = pfData[0];
- index = 0;
- //寻找序列中最大值以及其索引号
- for(j=1; j<k; j++)
- {
- if(pfData[j]>temp)
- {
- temp = pfData[j];
- index = j;
- }
- }
- //将序列尾部的值写入到当前序列中最大值处
- pfData[index] = pfData[k-1];//将序列中的最大值逐个覆盖
- pIndex[index] = k-1;
- }
- //粒子群中各个粒子最优适应度的中位数
- index = pIndex[nParticleNum/2];
- //中位数对应粒子的最优位置
- pos = cParticle[index].GetBestPosition();
- int dimension = cParticle[index].GetDimension();
- for(i=0; i<dimension; i++)
- midPosition[i] = pos[i];
- delete []pfData;
- delete []pIndex;
- }
- /*返回全局最优粒子的适应度*/
- float CParticleSwarm::GetGroupBestFitness()
- {
- return cParticle[nGroupBestIndex].GetBestFitness();
- }
- /*返回全局最优粒子的位置*/
- void CParticleSwarm::GetGroupBestPosition(float* bestPosition)
- {
- int dimension = cParticle[nGroupBestIndex].GetDimension();
- float *gBestPos;
- gBestPos = cParticle[nGroupBestIndex].GetBestPosition();
- for(int i=0; i<dimension; i++)
- bestPosition[i] = gBestPos[i];
- }
- /*检查粒子的速度信息是否越界*/
- void CParticleSwarm::CheckVelocity(float *velocity)
- {
- int dimension = cParticle[0].GetDimension();
- for(int i=0; i<dimension; i++)
- {
- //速度越界检查
- if(velocity[i]>pfMaxVelocity[i])//速度超过上界
- velocity[i] = pfMaxVelocity[i];
- if(velocity[i]<-pfMaxVelocity[i])//速度越过下界
- velocity[i] = -pfMaxVelocity[i];
- }
- }
- /*检查粒子的位置信息是否越界*/
- void CParticleSwarm::CheckPosition(float *position)
- {
- int dimension = cParticle[0].GetDimension();
- for(int i=0; i<dimension; i++)
- {
- //位置越界检查
- if(position[i]>pfMaxPosition[i])//位置超过上界
- position[i] = 2*pfMaxPosition[i]-position[i];
- if(position[i]<pfMinPosition[i])//位置越过下界
- position[i] = 2*pfMinPosition[i]-position[i];
- }
- }
- /*随机初始化粒子群*/
- void CParticleSwarm::Randomize()
- {
- if(!nParticleNum) return;
- static int kk=(unsigned)time(NULL);
- srand((unsigned)time(NULL)+kk++);
- int dimension = cParticle[0].GetDimension();
- nGroupBestIndex = 0;
- for(int i=0; i<nParticleNum; i++)
- {
- //初始化粒子的位置信息
- InitialPosition(i, dimension);
- //计算粒子群的适应度
- cParticle[i].CalculateFitness();
- //将粒子当前的适应度设置成粒子的最好适应度
- cParticle[i].SetBestFitness(cParticle[i].GetFitness());
- //查找初始粒子群中的最优粒子
- if(cParticle[i].GetFitness()<cParticle[nGroupBestIndex].GetFitness())
- nGroupBestIndex = i;
- }
- }
- /*生成新一代的粒子群*/
- void CParticleSwarm::ParticleFly()
- {
- if(!nParticleNum) return;
- static int tt=(unsigned)time(NULL);
- srand((unsigned)time(NULL)+tt++);
- int dimension = cParticle[0].GetDimension();
- for(int i=0; i<nParticleNum; i++)
- {
- //更新第i个粒子的位置信息
- UpdatePosition(i, dimension);
- //计算新一代粒子群的适应度值
- cParticle[i].CalculateFitness();
- //更新粒子的最优位置信息
- cParticle[i].UpdateBestPosition();
- }
- //跟新粒子群中全局最优粒子的索引号
- UpdateGroupBestIndex();
- }
- /*粒子群迭代进化(对于不同的实现算法可重载该函数实现)*/
- void CParticleSwarm::RunEpoch(int iteration)
- {
- //初始化粒子群
- Randomize();
- //粒子种群进化
- for(int i=0; i<iteration; i++)
- ParticleFly();
- }
- void CParticleSwarm::RunEpoch(float fitError)
- {
- //初始化粒子群
- Randomize();
- //粒子种群进化
- for(int i=0; ; i++)
- {
- ParticleFly();
- if(cParticle[nGroupBestIndex].GetBestFitness()<fitError)
- break;
- }
- }
- /*随机初始化粒子的位置信息(对于不同的更新算法可重载该函数实现)*/
- void CParticleSwarm::InitialPosition(int particleIndex, int dimension)
- {
- float *pos = new float[dimension];
- float *vel = new float[dimension];
- for(int i=0; i<dimension; i++)
- {
- //随机初始化粒子群的位置信息
- pos[i] = (float)rand()/(float)RAND_MAX
- *(pfMaxPosition[i]-pfMinPosition[i])+pfMinPosition[i];
- //随机初始化粒子群的速度信息
- vel[i] = (float)rand()/(float)RAND_MAX
- *pfMaxVelocity[i]-pfMaxVelocity[i]/2;
- }
- //设置初始粒子群的位置信息
- cParticle[particleIndex].SetPosition(pos);
- //设置初始粒子群的最优位置信息
- cParticle[particleIndex].SetBestPosition(pos);
- //设置初始粒子群的速度信息
- cParticle[particleIndex].SetVelocity(vel);
- delete []pos;
- delete []vel;
- }
- /*更新粒子的位置信息(对于不同的更新算法只需重载该函数实现即可)*/
- void CParticleSwarm::UpdatePosition(int particleIndex, int dimension)
- {
- float *pos, *bestPos, *gbestPos, *vel;
- //获取当前粒子的位置信息
- pos = cParticle[particleIndex].GetPosition();
- //获取局部最优粒子
- bestPos = cParticle[particleIndex].GetBestPosition();
- //全局最优粒子
- gbestPos = cParticle[nGroupBestIndex].GetBestPosition();
- //当前粒子的速度信息
- vel = cParticle[particleIndex].GetVelocity();
- for(int i=0; i<dimension; i++)
- {
- //更新粒子速度信息
- vel[i] = fMomentum*vel[i]/*惯性项*/
- +(float)rand()/(float)RAND_MAX*fC1*(bestPos[i]-pos[i])/*认知项*/
- +(float)rand()/(float)RAND_MAX*fC2*(gbestPos[i]-pos[i])/*社会项*/;
- }
- //检查粒子的速度信息是否越界
- CheckVelocity(vel);
- //位置信息更新
- for(i=0; i<dimension; i++)
- pos[i] += vel[i];//position += velocity;
- //检查粒子的位置信息是否越界
- CheckPosition(pos);
- }
- /***********************************************************************************
- MyParticle.h - 自定义粒子类头文件
- ************************************************************************************
- 类说明:
- 该类派生于粒子抽象基类,提供了一个自定义粒子类派生模式;
- 该类对粒子抽象基类中的成员变量进行内存分配;
- 该类实现了基类中计算粒子适应度的纯虚函数(针对不同实际问题只需修改该适应度函数);
- ************************************************************************************
- 作者:贾家磊,jiajialei816@163.com,中国地质大学(北京)地震勘探实验室,2011/11/30
- ************************************************************************************/
- #ifndef _MY_PARTICLE_H_JIAJIALEI
- #define _MY_PARTICLE_H_JIAJIALEI
- #include "Particle.h"
- class CMyParticle:public CParticle
- {
- public:
- ////////////////////
- //构造与析构部分
- ////////////////////
- //自定义粒子类缺省构造函数
- CMyParticle():CParticle() {};
- //自定义粒子类带参数构造函数
- CMyParticle(int dimension);
- //自定义粒子类析构函数
- virtual ~CMyParticle();
- ////////////////////
- //内存分配部分
- ////////////////////
- //设置自定义粒子维度并进行基类成员变量内存分配
- virtual void SetDimension(int dimension);
- ////////////////////
- //方法实现部分
- ////////////////////
- //计算自定义粒子的适应度(针对不同实际问题只需修改该函数)
- virtual void CalculateFitness();
- };
- #endif//_MY_PARTICLE_H_JIAJIALEI
- /***********************************************************************************
- MyParticle.cpp - 自定义粒子类的实现文件
- ************************************************************************************
- 类说明:
- 该类派生于粒子抽象基类,提供了一个自定义粒子类派生模式;
- 该类对粒子抽象基类中的成员变量进行内存分配;
- 该类实现了基类中计算粒子适应度的纯虚函数(针对不同实际问题只需修改该适应度函数);
- ************************************************************************************
- 作者:贾家磊,jiajialei816@163.com,中国地质大学(北京)地震勘探实验室,2011/11/30
- ************************************************************************************/
- #include "MyParticle.h"
- /*自定义粒子类带参数构造函数(分配内存空间)*/
- CMyParticle::CMyParticle(int dimension):CParticle(dimension)
- {
- pfPosition = new float[nDimension];
- pfVelocity = new float[nDimension];
- pfBestPosition = new float[nDimension];
- }
- /*析构自定义粒子*/
- CMyParticle::~CMyParticle()
- {
- if(nDimension)
- {
- delete []pfPosition;
- delete []pfVelocity;
- delete []pfBestPosition;
- }
- }
- /*设置自定义粒子维度并进行基类成员变量内存分配*/
- void CMyParticle::SetDimension(int dimension)
- {
- if(nDimension)
- {
- delete []pfPosition;
- delete []pfVelocity;
- delete []pfBestPosition;
- }
- nDimension = dimension;
- pfPosition = new float[nDimension];
- pfVelocity = new float[nDimension];
- pfBestPosition = new float[nDimension];
- }
- /*计算自定义粒子的适应度(针对不同实际问题只需修改该函数)*/
- #include "math.h"
- void CMyParticle::CalculateFitness()
- {
- //针对实际问题需完成的...
- // Particle::fFitness = 1.1f;
- }
- /***********************************************************************************
- PSO.h - 标准粒子群算法类头文件
- ************************************************************************************
- 类说明:
- 该类派生于粒子群基类,提供了一个自定义粒子群类派生模式;
- 该类对粒子群基类中的成员变量进行内存分配;
- 该类实现了基类的标准粒子群算法
- ************************************************************************************
- 作者:贾家磊,jiajialei816@163.com,中国地质大学(北京)地震勘探实验室,2011/11/30
- ************************************************************************************/
- #ifndef _PSO_H_JIAJIALEI
- #define _PSO_H_JIAJIALEI
- #include "MyParticle.h"
- #include "ParticleSwarm.h"
- class CPSO : public CParticleSwarm
- {
- public:
- ////////////////////
- //构造与析构部分
- ////////////////////
- //标准粒子群类缺省构造函数
- CPSO():CParticleSwarm() {};
- //标准粒子群类带参数构造函数
- CPSO(int dimension, int particleNum);
- //标准粒子群类析构函数
- virtual ~CPSO();
- };
- #endif//_ADAPTIVE_EXTENDED_PSO_H_JIAJIALEI
- /***********************************************************************************
- PSO.cpp - 标准粒子群算法类的实现文件
- ************************************************************************************
- 类说明:
- 该类派生于粒子群基类,提供了一个自定义粒子群类派生模式;
- 该类对粒子群基类中的成员变量进行内存分配;
- 该类实现了基类的标准粒子群算法
- ************************************************************************************
- 作者:贾家磊,jiajialei816@163.com,中国地质大学(北京)地震勘探实验室,2011/11/30
- ************************************************************************************/
- #include "PSO.h"
- /*设置标准粒子群并进行基类成员变量内存分配*/
- CPSO::CPSO(int dimension, int particleNum)
- :CParticleSwarm(dimension, particleNum)
- {
- cParticle = new CMyParticle[particleNum];
- for(int i=0; i<particleNum; i++)
- cParticle[i].SetDimension(dimension);//单个粒子分配内存
- pfMinPosition = new float[dimension];
- pfMaxPosition = new float[dimension];
- pfMaxVelocity = new float[dimension];
- }
- /*标准粒子群类析构函数*/
- CPSO::~CPSO()
- {
- if(nParticleNum)
- delete []cParticle;
- if(pfMinPosition != NULL)
- delete []pfMinPosition;
- if(pfMaxPosition != NULL)
- delete []pfMaxPosition;
- if(pfMaxVelocity != NULL)
- delete []pfMaxVelocity;
- }
|