上一回说了基本粒子群算法的实现,并且给出了C语言代码。这一篇主要讲解影响粒子群算法的一个重要参数---w。我们已经说过粒子群算法的核心的两个公式为:

Vid(k+1)=w*Vid(k)+c1*r1*(Pid(k)-Xid(k))+c2*r2*(Pgd(k)-Xid(k))
Xid(k+1) = Xid(k) + Vid(k+1)

标红的w即是本次我们要讨论的参数。之前w是不变的(默认取1),而现在w是变化的,w称之为惯性权重,体现的是粒子继承先前速度的能力。

经验表明:一个较大的惯性权重有利于全局搜索,而一个较小的惯性权重则更有利于局部搜索。为了更好地平衡算法的全局搜索能力与局部搜索能力,Shi.Y提出了线性递减惯性权重(LDIW)
 即:w(k)
= w_end + (w_start- w_end)*(Tmax-k)/Tmax。其中w_start 为初始惯性权重,w_end
为迭代至最大次数时的惯性权重;k为当前迭代次数,
Tmax为最大迭代次数。一般来说,w_start=0.9,w_end=0.4时,算法的性能最好。这样随着迭代的进行,惯性权重从0.9递减到0.4,迭代初期较大的惯性权重使算法保持了较强的全局搜索能力。而迭代后期较小的惯性权重有利于算法进行更精确的局部搜索。线性惯性权重,只是一种经验做法,常用的惯性权重还包括
以下几种。
 (3) w(k) = w_start - (w_start-w_end)*(k/Tmax)^2
 (4) w(k) = w_start + (w_start-w_end)*(2*k/Tmax - (k/Tmax)^2)
 (5) w(k) = w_end*(w_start/w_end)^(1/(1+c*k/Tmax)) ,c为常数,比如取10等。
 本例的目的就是比较这5种不同的w取值,对于PSO寻优的影响。比较的方法为每种w取值,重复实验若干次(比如100次),比较平均最优解的大小,陷入次优解的次数,以及接近最优解的次数。 这样对于5种方法的优劣可以有一个直观的比较。

代码如下:

/*
* 使用C语言实现粒子群算法(PSO) 改进版本
* 参考自《MATLAB智能算法30个案例分析》
* update: 16/12/3
* 主要改进的方面体现在w的选择上面
* 本例的寻优非线性函数为
* f(x,y) = sin(sqrt(x^2+y^2))/(sqrt(x^2+y^2)) + exp((cos(2*PI*x)+cos(2*PI*y))/2) - 2.71289
* 该函数有很多局部极大值点,而极限位置为(0,0),在(0,0)附近取得极大值
*/
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<time.h>
#define c1 1.49445 //加速度因子一般是根据大量实验所得
#define c2 1.49445
#define maxgen 300 // 迭代次数
#define repeat 100 // 重复实验次数
#define sizepop 20 // 种群规模
#define popmax 2 // 个体最大取值
#define popmin -2 // 个体最小取值
#define Vmax 0.5 // 速度最大值
#define Vmin -0.5 //速度最小值
#define dim 2 // 粒子的维数
#define w_start 0.9
#define w_end 0.4
#define PI 3.1415926 //圆周率 double pop[sizepop][dim]; // 定义种群数组
double V[sizepop][dim]; // 定义种群速度数组
double fitness[sizepop]; // 定义种群的适应度数组
double result[maxgen]; //定义存放每次迭代种群最优值的数组
double pbest[sizepop][dim]; // 个体极值的位置
double gbest[dim]; //群体极值的位置
double fitnesspbest[sizepop]; //个体极值适应度的值
double fitnessgbest; // 群体极值适应度值
double genbest[maxgen][dim]; //每一代最优值取值粒子 //适应度函数
double func(double * arr)
{
double x = *arr; //x 的值
double y = *(arr+); //y的值
double fitness = sin(sqrt(x*x+y*y))/(sqrt(x*x+y*y)) + exp((cos(*PI*x)+cos(*PI*y))/) - 2.71289;
return fitness; }
// 种群初始化
void pop_init(void)
{
for(int i=;i<sizepop;i++)
{
for(int j=;j<dim;j++)
{
pop[i][j] = (((double)rand())/RAND_MAX-0.5)*; //-2到2之间的随机数
V[i][j] = ((double)rand())/RAND_MAX-0.5; //-0.5到0.5之间
}
fitness[i] = func(pop[i]); //计算适应度函数值
}
}
// max()函数定义
double * max(double * fit,int size)
{
int index = ; // 初始化序号
double max = *fit; // 初始化最大值为数组第一个元素
static double best_fit_index[];
for(int i=;i<size;i++)
{
if(*(fit+i) > max)
max = *(fit+i);
index = i;
}
best_fit_index[] = index;
best_fit_index[] = max;
return best_fit_index; }
// 迭代寻优,传入的参数为一个整数,取值为1到5,分别代表5种不同的计算w的方法
void PSO_func(int n)
{
pop_init();
double * best_fit_index; // 用于存放群体极值和其位置(序号)
best_fit_index = max(fitness,sizepop); //求群体极值
int index = (int)(*best_fit_index);
// 群体极值位置
for(int i=;i<dim;i++)
{
gbest[i] = pop[index][i];
}
// 个体极值位置
for(int i=;i<sizepop;i++)
{
for(int j=;j<dim;j++)
{
pbest[i][j] = pop[i][j];
}
}
// 个体极值适应度值
for(int i=;i<sizepop;i++)
{
fitnesspbest[i] = fitness[i];
}
//群体极值适应度值
double bestfitness = *(best_fit_index+);
fitnessgbest = bestfitness; //迭代寻优
for(int i=;i<maxgen;i++)
{
for(int j=;j<sizepop;j++)
{
//速度更新及粒子更新
for(int k=;k<dim;k++)
{
// 速度更新
double rand1 = (double)rand()/RAND_MAX; //0到1之间的随机数
double rand2 = (double)rand()/RAND_MAX;
double w;
double Tmax = (double)maxgen;
switch(n)
{
case :
w = ;
case :
w = w_end + (w_start - w_end)*(Tmax-i)/Tmax;
case :
w = w_start -(w_start-w_end)*(i/Tmax)*(i/Tmax);
case :
w = w_start + (w_start-w_end)*(*i/Tmax-(i/Tmax)*(i/Tmax));
case :
w = w_end*(pow((w_start/w_end),(/(+*i/Tmax))));
default:
w = ;
}
V[j][k] = w*V[j][k] + c1*rand1*(pbest[j][k]-pop[j][k]) + c2*rand2*(gbest[k]-pop[j][k]);
if(V[j][k] > Vmax)
V[j][k] = Vmax;
if(V[j][k] < Vmin)
V[j][k] = Vmin;
// 粒子更新
pop[j][k] = pop[j][k] + V[j][k];
if(pop[j][k] > popmax)
pop[j][k] = popmax;
if(pop[j][k] < popmin)
pop[j][k] = popmin;
}
fitness[j] = func(pop[j]); //新粒子的适应度值
}
for(int j=;j<sizepop;j++)
{
// 个体极值更新
if(fitness[j] > fitnesspbest[j])
{
for(int k=;k<dim;k++)
{
pbest[j][k] = pop[j][k];
}
fitnesspbest[j] = fitness[j];
}
// 群体极值更新
if(fitness[j] > fitnessgbest)
{
for(int k=;k<dim;k++)
gbest[k] = pop[j][k];
fitnessgbest = fitness[j];
}
}
for(int k=;k<dim;k++)
{
genbest[i][k] = gbest[k]; // 每一代最优值取值粒子位置记录
}
result[i] = fitnessgbest; // 每代的最优值记录到数组
}
} // 主函数
int main(void)
{
clock_t start,finish; //程序开始和结束时间
start = clock(); //开始计时
srand((unsigned)time(NULL)); // 初始化随机数种子
for(int i=;i<=;i++)
{
int near_best = ; // 接近最优解的次数
double best_sum = ; // 重复最优值求和
double best = ; // 重复实验得到的最优解
for(int j=;j<repeat;j++)
{
PSO_func(i); // 第i种w参数取值
double * best_fit_index = max(result,maxgen);
double best_result = *(best_fit_index+); //最优解
if(best_result > 0.95)
near_best++;
if(best_result>best)
best = best_result;
best_sum += best_result;
}
double average_best = best_sum/repeat; //重复实验平均最优值
printf("w参数的第%d种方法:\n",i);
printf("重复实验%d次,每次实验迭代%d次,接近最优解的实验次数为%d次,求得最优值为:%lf,平均最优值为:%lf\n",repeat,maxgen,near_best,best,average_best);
}
finish = clock(); //结束时间
double duration = (double)(finish - start)/CLOCKS_PER_SEC; // 程序运行时间
printf("程序运行耗时:%lf\n",duration);
return ;
}

程序运行结果如下:

从实验的结果来看,第3种w的取法,无论是接近最优解的的次数,最优值大小,还是平均最优值,都是5种里面最好的。其原因解释如下:通过w的表达式可以看出,前期w变化较慢,取值较大,维持了算法的全局搜索能力;后期w变化变化较快,极大地提高了算法的局部搜索能力寻优能力,从而取得了很好的求解效果。

从总体上来看,在大部分的情况下,无论w是5种里面哪种取法,得到的结果都很好地接近实际的最优解,这说明了粒子群算法的搜索寻优能力还是很强的。

C语言实现粒子群算法(PSO)二的更多相关文章

  1. C语言实现粒子群算法(PSO)一

    最近在温习C语言,看的书是<C primer Plus>,忽然想起来以前在参加数学建模的时候,用过的一些智能算法,比如遗传算法.粒子群算法.蚁群算法等等.当时是使用MATLAB来实现的,而 ...

  2. 算法(三)粒子群算法PSO的介绍

    一.引言 在讲算法之前,先看两个例子: 例子一:背包问题,一个书包,一堆物品,每个物品都有自己的价值和体积,装满书包,使得装的物品价值最大. 例子二:投资问题,n个项目,第i个项目投资为ci 收益为p ...

  3. 【比较】粒子群算法PSO 和 遗传算法GA 的相同点和不同点

    目录 PSO和GA的相同点 PSO和GA不同点 粒子群算法(PSO)和遗传算法(GA)都是优化算法,都力图在自然特性的基础上模拟个体种群的适应性,它们都采用一定的变换规则通过搜索空间求解. PSO和G ...

  4. 粒子群算法-PSO

    粒子群优化算法 1. 背景知识 1995年美国社会心理学家Kennedy和电气工程师Eberhart共同提出粒子群优化算法(Particle Swarm Optimization, PSO).PSO算 ...

  5. 粒子群算法(PSO)算法解析(简略版)

    粒子群算法(PSO) 1.粒子群算法(PSO)是一种基于群体的随机优化技术: 初始化为一组随机解,通过迭代搜寻最优解. PSO算法流程如图所示(此图是从PPT做好,复制过来的,有些模糊) 2.PSO模 ...

  6. 粒子群算法(PSO)

    这几天看书的时候看到一个算法,叫粒子群算法,这个算法挺有意思的,下面说说我个人的理解: 粒子群算法(PSO)是一种进化算法,是一种求得近似最优解的算法,这种算法的时间复杂度可能会达到O(n!),得到的 ...

  7. 粒子群算法 Particle Swarm Optimization, PSO(转贴收藏)

    粒子群算法(1)----粒子群算法简介 http://blog.csdn.net/niuyongjie/article/details/1569671 粒子群算法(2)----标准的粒子群算法 htt ...

  8. 基于粒子群算法求解求解TSP问题(JAVA)

    一.TSP问题 TSP问题(Travelling Salesman Problem)即旅行商问题,又译为旅行推销员问题.货郎担问题,是数学领域中著名问题之一.假设有一个旅行商人要拜访n个城市,他必须选 ...

  9. 【智能算法】粒子群算法(Particle Swarm Optimization)超详细解析+入门代码实例讲解

    喜欢的话可以扫码关注我们的公众号哦,更多精彩尽在微信公众号[程序猿声] 01 算法起源 粒子群优化算法(PSO)是一种进化计算技术(evolutionary computation),1995 年由E ...

随机推荐

  1. 第一章 Java的I/O演进之路

    I/O基础入门 Java的I/O演进 第一章 Java的I/O演进之路 1.1 I/O基础入门 1.1.1 Linux网络I/O模型简介 根据UNIX网络编程对I/O模型的分类,UNIX提供了5中I/ ...

  2. 总结oninput、onchange与onpropertychange事件的用法和区别,onchange

    前端页面开发的很多情况下都需要实时监听文本框输入,比如腾讯微博编写140字的微博时输入框hu9i动态显示还可以输入的字数.过去一般都使用onchange/onkeyup/onkeypress/onke ...

  3. 实现标记datagridview标题并导出Excel的功能

    最近在学习winform,国庆前被布置了一个小任务,好不容易大致做出来了,决定记录下来,以此加深印象. 先说下需求:这是一个导入话单标记后并导出的功能 1. 选择excel文件 2. 定义字段   日 ...

  4. 我需要在Web上完成一个图片上传的功能后续(+1)

    微信入口施工完成.关键字识别中增加了本次活动的"关键字",在系统中增加了链接.不过,由于地址包含私密关键参数,这里隐藏,敬请原谅. 下一步,微信链接的地址页面是要对微信用户的信息进 ...

  5. 在引用KindEditor编辑器时,运行时出现以下错误:错误46 找不到类型或命名空间名称“LitJson”(是否缺少 using 指令或程序集引用?)

    将asp.net下bin文件夹下的文件LitJSON.dll拷贝到工程的bin目录下,并在工程中添加引用 在后台加入: using LitJson;

  6. MYSQL命令行使用指南

    一.连接MYSQL. 格式: mysql -h主机地址 -u用户名 -p用户密码 1.例1:连接到本机上的MYSQL. 首先在打开DOS窗口,然后进入目录 mysqlbin,再键入命令mysql -u ...

  7. SoapUI新版本“Ready!API 1.80”体验

    做过接口测试的朋友,肯定都知道一个工具--SoapUI,它强大的功能与集成用例的特性,让不管是开发还是测试,都喜欢用它.在经历了众多版本后,SmartBear公司将SoapUI 从进行了大改版,这也是 ...

  8. Java项目:学生成绩管理系统(二)

    学生成绩管理系统(二):项目介绍 一.设计要求: 1.1 简单的图形界面登录功能. 1.2 对数据库的的信息的查询功能. 1.3 对数据库的的信息的修改功能. 1.4 对数据库的的信息的删除功能. 1 ...

  9. tab切换-淘宝案例

    案例: html: <body> <div class="wrap" id="wrap"> <div class="no ...

  10. Xcode模拟器不显示SDK版本,反而显示设备ID的解决办法

    今天在应用程序中修改了Xcode app 的名称,结果导致Xcode模拟器不显示SDK版本,反而显示设备ID了,感觉特别的忧伤......如图: 进到Xcode->window->Devi ...