一种“邻居环”的简易实现

引言:粒子群优化算法(PSO)最经典的莫过于GBest-全局版和LBest-局部版,而这两个版本也在2007中被发明者的其中之一定义为Standard,它建议以后人们改进的各种粒子群算法在比较算法优劣的时候,这两个都要拿来比较(确实,现在大家绝大部分都只实现GBest版本,因为容易,LBest相对较难一点),因为这两种方法非常典型,前者在收敛速度上面具有优势,但是较容易陷入局部极小点,因为一旦有一个较优的点被找到,大家都冲过去了;后者在搜索全局最优解上有优势,但是收敛速度较慢,因为一旦你定义了你的邻居,只有邻居的最优解会影响你的运行轨迹,邻居之外的最有信息要经过一个一个的迭代传播才到你这里。

所以在实现后者的时候就需要“邻居环”的东东来把种群里面的所有粒子都要连接起来。其实,全局版本是邻居版本的特例,因为你的邻居一旦为种群中粒子数目的一半,就它们全部连接起来了~~~邻居的个数也就决定了粒子群在搜索的时候,在收敛速度(exploitation-开发能力)和寻找全局最优解能力(exploration-探索能力)之间的一个tradeoff~~~

“邻居环”是我自己定义的一种名称而已:它首先是一个环,但是环中的每个个体(在PSO中就是粒子)都可以定义自己邻居的个数。下图为每个个体只有一个邻居——ring

   GBest一种“邻居环”的简易实现_第1张图片  LBest一种“邻居环”的简易实现_第2张图片

                   

GBest速度更新公式:


LBest速度更新公式:


在实现方面,相对于GBest版本,区别只是在得到速度公式中的是Pgd还是Pid,前者只是需要将每个粒子比较一下即可,但是后者的话你到得到每个粒子在其邻居范围内的局部最优解,也就是在邻居中找到“最牛”的解,这就有点蛋疼了,主要是处理头和尾的时候把他们连成一个环~~~

前天在实现的时候,在“狗屎”一样的代码中实现了一句还算比较巧妙的~~~其中,LBest_LDW_NUM为自定义邻居的个数。i为第i个粒子。P_Num为粒子数目。P_Fitness就是拿来比较的评价指标。

具体参数含义看C语言实现标注PSO算法。

/*更新每个粒子的邻居极值位置LBest*/

for (j=-LBest_LDW_NUM;j<=LBest_LDW_NUM;j++)
{
	/*一个粒子的邻居极值位置*/
	if (swarm.Particle[((i+j)+P_Num)%P_Num].P_Fitness < swarm.Particle[swarm.LBestIndex[i]].P_Fitness)
		swarm.LBestIndex[i]=((i+j)+P_Num)%P_Num;
}

这条语句“((i+j)+P_Num)%P_Num”处理了头和尾的负数和大于粒子群的数目的情况。


PS:记录写代码过程中的一个感受来警示自己:没有实现“低耦合,高内聚,包括变量和函数”的“模块化程序”(可能只是文件模块化了,伪模块化)都是坑爹的~~~这个对扩展性更伤~~~

一种“邻居环”的简易实现_第3张图片

你可能感兴趣的:(c,优化,算法,扩展,粒子群)