基于粒子群优化的无约束50维Rosenbrock函数求解
基于粒子群优化的无约束50维Rosenbrock函数求解
一、问题重述
无约束50维的Rosenbrock函数可以描述如下:
其中, 0
要求按PSO算法思想设计一个该问题的求解算法。
Rosenbrock是一个著名的测试函数,也叫香蕉函数,其特点是该函数虽然是单峰函数,在[100,100]n上只有一个全局极小点,但它在全局极小点临近的狭长区域内取值变化极为缓慢,常用于评价算法的搜索性能。这种实优化问题非常适合于使用粒子群优化算法来求解。
二、算法
2.1算法设计:
编码
因为问题的维数为50,且可以取[-30,30]范围内的所有实数。所以每个粒子拥有速度和位置的50维的实数向量,每个x的范围都在[-30,30]。
初始化范围
根据问题要求,设定为[-30,30]。因为最大移动范围为60,我们知道,可以将最大速度设定为Vmax=60。
种群大小
查找资料说种群大小在20-40之间,这里设定总群大小n=40。
停止准则
设定为最大迭代次数1000次。当达到迭代次数时,停止运算。
惯性权重
采用固定权重0.5。惯性权重比较重要,最后在算法实现后,多测试几个权重。
学习因子
查找资料有三种说法,一种是两个学习因子相等,C1=C2=2。一种是两个学习因子不等,C1=2.8,C2=1.3。准备在算法里都试一试。
邻域拓扑结构
使用星形拓扑结构,即全局版本的粒子群优化算法。
2.2算法求解
粒子群优化的实施步骤:
第一步:初始化粒子群。产生n个粒子,每个粒子随机生成其50维向量的位置和速度。此时设置进化代数为1。
第二步:评价每一个粒子。计算每一个粒子Rosenbrock函数的值,并记录粒子历史最优解和粒子群历史最优解。
第三步:移动值。每一个粒子根据自己的历史最优解和粒子群的历史最优解设置自己的移动速度。并根据移动速度移动到下一个位置。并返回重新评价。
第四步:终止条件判断。当进化代数达到终止代数时,终止运算。输出最优解。
三、算法实现
本文使用C++进行算法实现。编写了两个类,分别是粒子类,和粒子群类。下面分别介绍两个类。
3.1粒子类
粒子类主要描述单个粒子对象。
粒子类成员主要包括:粒子维数,粒子位置,粒子速度,粒子自身历史最优解,位置限制范围,速度限制范围,学习因子,惯性权重。
粒子类函数主要包括:粒子初始化函数,粒子移动函数,粒子评价函数,粒子速度更新函数,打印函数和一些成员读取函数。
初始化函数根据给定维数,约束。随机生成d维位置和速度。
移动函数根据速度变量将粒子移动到下一个位置,并且使移动范围不超过限制范围。
粒子评价函数负责计算当前粒子所在位置Rosenbrock函数的数值,并和自身历史最优解进行比较,若小于最优解,则更新最优解。
速度更新函数根据粒子群最优解和自身最优解更新下一次运动的速度,具体公式为: 。
打印函数负责输出当前粒子的信息。粒子位置,速度和Rosenbrock函数值。
以下为粒子类的声明部分代码。
class Particle
{
protected:
int d; //维数
//TODO:试试用智能指针写
double *x; //粒子位置
double *v; //粒子速度
double *bestx; //记录最优一次位置
double value;
double bestvalue; //记录最优值
double xmin;
double xmax;
double vmax;
double vmin;
double c1;
double c2;
double omega;
public:
Particle();
~Particle();
void print();
void init(int dsize, double min, double max);//初始化粒子,dsize是维数
void move(); //粒子移动
double UpdateValue(); //更新粒子值
void UpdateSpeed(double *bestpx, double omega);
double *getx();
};
3.2粒子群类
粒子群类描述整个粒子群对象。
粒子群类成员包括粒子数,粒子群,粒子群最优解,进化代数,粒子维数,粒子位置约束。
粒子群类函数包括初始化,寻找最优,粒子群移动,粒子群更新速度,运行,打印和访问粒子群类成员函数。
初始化函数根据给定的种群大小,粒子维数,粒子限制,最大代数生成粒子群。
寻找最优函数,函数调用每个粒子的评价函数,并且把每个粒子的最优值和粒子群的最优值做比对,若更小,则更新粒子群最优值和最优位置。
粒子群移动函数,调用每个粒子移动函数。
打印函数打印粒子群的信息,打印最优解,最优解位置,运行代数。
运行函数根据运行代数,循环执行粒子移动,寻找最优,更新速度。并且在达到最大代数使停止工作。
class PSO
{
protected:
int n; //粒子数
Particle *p; //粒子群
double *bestpx; //最优粒子
double bestpvalue;
int maxgen;
int gen;
int dsize; //粒子维数
int min; //粒子最小、最大取值范围
int max;
public:
PSO();
~PSO();
void init(int nsize, int dsize, int min, int max, int maxgen);
void print(int i);
void findbest();
void SwarmMove();
void SwarmUpdateSpeed();
void run();
double getbestpvalue();
};
3.3主函数调用
执行整个算法,主函数中需要定义一个粒子群类,并且初始化类。这里使用种群数40,例子维数50,限制[-30,30],运行代数1000来初始化对象。之后调用粒子类的运行函数即可。
四、算法评价
4.1编译和运行环境
代码使用C++进行编写,在Windows 10平台进行编译。编译平台使用VS2013,使用release方式编译可执行程序。
运行平台介绍。
软件环境:
Windows10版本1709。
硬件环境:
CPU: Intel E3-1230 V3 4核心8线程 @3.3GHz
内存:16GB DDR3 1600MHz
4.2算法运行结果
根据Rosenbrock函数的公式,可以很清楚的看出最优点为50个点均为1时,最优解为0。这里设置运行代数分别为10,100,1000,1000。各运行100次。观察计算出的最优解。时间为运行100次所用时间。
表1 计算结果
最小值 |
平均值 |
最大值 |
时间/s |
|
n=10 |
2.981e+008 |
4.63e+008 |
5.82e+008 |
0.122 |
n=100 |
1.45e+007 |
5.36e+007 |
1.18e+008 |
1.06 |
n=1000 |
264.51 |
1.62e+006 |
8.00e+007 |
9.74 |
n=10000 |
47.23 |
8.00e+007 |
819889 |
27.02 |
可以看出,进化代数增大可以带来求解平均值下降。但是进化代数1000变为10000时,进化效果不明显。本文当前的求解结果跟查到的最优解差距较大,之后会去再寻找原因,之后可以采用变惯性系数,变学习因子的方法改进算法。
代码运行结果: