问题:用粒子群算法求函数f(x)=xsinx*cos2x-2*x*sin3x的最大值,同时可以求出当x取多少时原函数有最大值?
粒子群算法:
1.同遗传算法一样先要随机生成鸟群的位置和速度(相当于遗传算法中随机生成的种群),其实就是在特定的范围内生成随机数
2.需要开始一个大循环,可以理解为各个鸟进行信息交流后又开始去新的位置寻找食物。
3.需要记录下每只“鸟”历史上的最优位置(因为会有循环嘛,所以一只鸟会有好多位置,只要记录下最优位置就好),何为最优是通过类似适应度函数来界定的,这里因为是求原函数最大值,随意直接可以将原函数作为适应度函数。
4.需要记录所有鸟中位置最优的那个,同时可以记录下这只鸟对应的适应度函数。至于为啥要记录最优位置,是因为后面速度更新的时候需要用到。
v[i] = v[i]*w + c1*Math.random()*(xm[i]-x[i]) + c2*Math.random()*(ym-x[i]);//速度更新 。其中xm[i]就是每只鸟历史上最优的位置,xm是数组额,大小为鸟的数量;而ym是所有群中那个最优的位置,当然也是所有循环中最优的那个,ym是一个数额。
5.进行速度和位置更新,这里可以理解为所有的鸟已经进行了信息交流,为了更好的寻找食物,它们需要飞到了另一个位置。其中就是因为速度的更新才会有位置的更新,可以理解为鸟每次循环(信息交流)后只会飞固定的时间,比如飞一秒。这样只要确定了速度就确定了下一次鸟会飞到哪个位置。这里的速度和位置更新公式也就是PSO的核心算法部分。
盗了一位大哥的图见谅https://blog.csdn.net/daaikuaichuan/article/details/81382794
6.既然速度和位置都已经更新啦,就是鸟已经飞到别的位置了嘛,可以从3.开始循环了嘛
用matlab感觉对编程的思想理解没有太大帮助啊,毕竟大多都是别人封装好的函数,所以用java写一下吧,
package pso;
/*利用PSO(粒子群算法)计算f(x)=xsinx*cos2x-2*x*sin3x;的最大值*/
public class PSO {
public static void main(String[] arg) {
int N = 50;//初始种群数
int ger = 100;//迭代次数
double w = 0.8;//惯性权重
double c1 = 0.5;//自我学习因子
double c2 = 0.4;//群体学习因子
double[] xlimit = {0,20};//设置位置参数限制
double[] vlimit = {-1,1};//设置速度限制
double[] x = new double[N];//用来记录x(鸟群位置)的数组
double[] v = new double[N];//用来记录v(鸟群速度)的数组
double[] fx = new double[N];//用来记录适应度函数的数组,因为是求最大值,可以直接用原函数作为适应度函数
double[] fxm = new double[N];//用来记录个体最佳适应度
double[] xm = new double[N];//用来记录个体最佳位置
double ym = (xlimit[1] - xlimit[0])/2;//群体最佳位置
double fym = 0;//群体最佳适应度
for (int i=0; i<N; i++)//产生xlimit范围内的随机数,相当于生成鸟群的位置
x[i] = xlimit[0] + (xlimit[1] - xlimit[0])*Math.random();
for (int i=0; i<N; i++)
v[i] = Math.random();
for (; ger>=0; ger--) {//总的迭代次数
for (int i=0; i<N; i++)
fx[i] = x[i]*Math.sin(x[i])*Math.cos(2*x[i]) - 2*x[i]*Math.sin(3*x[i]);//计算各个位置的适应度函数
for (int i=0; i<N; i++) {
if (fx[i]>fxm[i]) {
fxm[i] = fx[i];//更新个体历史最佳适应度
xm[i] = x[i]; //更新个体历史最佳位置
}
}
for (int i=0; i<N; i++) {
if (fym<fxm[i]) {
fym = fxm[i];//更新群体最佳适应度
ym = xm[i];//更新群体最佳位置
}
}
for (int i=0; i<N; i++) {
v[i] = v[i]*w + c1*Math.random()*(xm[i]-x[i]) + c2*Math.random()*(ym-x[i]);//速度更新
if (v[i]<vlimit[0])
v[i] = vlimit[0];
if (v[i]>vlimit[1])
v[i] = vlimit[1];//边界处理防止速度超出已给的范围
}
for (int i=0; i<N; i++)
x[i] = x[i] + v[i];//位置更新
}
System.out.println("f(x)在x="+ym+"时取得最大值"+fym);
}
}