粒子群算法
粒子群算法(PSO,Particle Swarm Optimization),也称粒子群优化算法或鸟群觅食算法。1995年由J. Kennedy和R. C. Eberhart等开发的一种新的进化算法(Evolutionary Algorithm - EA)。
粒子群优化算法的基本思想是利用群体中个体之间的信息共享,从而使得整个群体的运动在问题求解空间中产生从无序到有序的演化过程,从而获得问题的最优解。
粒子群算法的详细介绍,网上已经有很多资料,这里就不再赘述。画个标准算法的流程图吧。
然后推荐几个学习链接:
https://mp.weixin.qq.com/s/Vz6BFqzFmQLwgQz6agjG0A
https://mp.weixin.qq.com/s/axln8SohDXpHDAeJ2EhKQg
https://mp.weixin.qq.com/s/3Os2ZxLkFM6wKzY6wLQ9zA
……
本文要求解极值的非线性函数为
下面直接上代码:
程序中种群规模为50,迭代次数为500,位置范围为[-2, 2],速度范围为[-0.5, 0.5],两个加速因子均为1.49445。/* 参考资料:https://blog.csdn.net/hcc199521/article/details/53445656?utm_medium=distribute.pc_relevant.none-task-blog-title-2&spm=1001.2101.3001.4242求解以下二元函数的最大值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.71289s.t. x∈[-2, 2] y∈[-2, 2]*/#include #include #include #include #include #include #include #define g_dC1 1.49445 /* 加速因子 */#define g_dC2 1.49445 /* 加速因子 */#define g_nG 500 /* 迭代次数 */#define g_nPopulationNum 50 /* 种群大小 */#define g_nXMin -2#define g_nXMax 2#define g_nYMin -2#define g_nYMax 2#define g_dVMin -0.5#define g_dVMax 0.5#define PI 3.1415926typedef struct stParticle_s{ double dX; double dY; double dVX; double dVY; double dFitness;}stParticle_t;stParticle_t g_astParticles[g_nPopulationNum]; /* 每一代种群数据 */stParticle_t g_astPBestParticle[g_nPopulationNum]; /* 各粒子极值数据 */stParticle_t g_stGBestParticle; /* 群体全局极值数据 *//* 计算粒子的适应度值 */void CalFitnessPerParticle(stParticle_t *stParticle){ stParticle->dFitness = sin(sqrt(stParticle->dX * stParticle->dX + stParticle->dY * stParticle->dY))/(sqrt(stParticle->dX * stParticle->dX + stParticle->dY * stParticle->dY)) + exp((cos(2 * PI * stParticle->dX) + cos(2 * PI * stParticle->dY))/2) - 2.71289;}void CalFitness(){ for (int i = 0; i < g_nPopulationNum; i++) { CalFitnessPerParticle(&(g_astParticles[i])); }}/* 初始化 */void Initialization(){ /* 初始化种群数据 */ for (int i = 0; i < g_nPopulationNum; i++) { g_astParticles[i].dX = (((double)rand()) / RAND_MAX - 0.5) * 4; /* -2到2之间的随机数 */ g_astParticles[i].dY = (((double)rand()) / RAND_MAX - 0.5) * 4; /* -2到2之间的随机数 */ g_astParticles[i].dVX = ((double)rand()) / RAND_MAX - 0.5; /* -0.5到0.5之间的随机数 */ g_astParticles[i].dVY = ((double)rand()) / RAND_MAX - 0.5; /* -0.5到0.5之间的随机数 */ } /* 初始化全局数据 */ g_stGBestParticle.dX = 0.0; g_stGBestParticle.dY = 0.0; g_stGBestParticle.dVX = 0.0; g_stGBestParticle.dVY = 0.0; g_stGBestParticle.dFitness = DBL_MIN; for (int i = 0; i { g_astPBestParticle[i].dX = 0.0; g_astPBestParticle[i].dY = 0.0; g_astPBestParticle[i].dVX = 0.0; g_astPBestParticle[i].dVY = 0.0; g_astPBestParticle[i].dFitness = DBL_MIN; }}/* 找到每个粒子各自的极值,以及整体的极值 */void SearchPGBestParticle(){ for (int i = 0; i < g_nPopulationNum; i++) { /* 找到每个粒子各自的极值(该粒子每代的极值进行比较) */ if (g_astPBestParticle[i].dFitness < g_astParticles[i].dFitness) { g_astPBestParticle[i].dX = g_astParticles[i].dX; g_astPBestParticle[i].dY = g_astParticles[i].dY; g_astPBestParticle[i].dVX = g_astParticles[i].dVX; g_astPBestParticle[i].dVY = g_astParticles[i].dVY; g_astPBestParticle[i].dFitness = g_astParticles[i].dFitness; } /* 找到全局最优粒子 */ if (g_stGBestParticle.dFitness < g_astParticles[i].dFitness) { g_stGBestParticle.dX = g_astParticles[i].dX; g_stGBestParticle.dY = g_astParticles[i].dY; g_stGBestParticle.dVX = g_astParticles[i].dVX; g_stGBestParticle.dVY = g_astParticles[i].dVY; g_stGBestParticle.dFitness = g_astParticles[i].dFitness; } }}/* 更新粒子的位置和速度 */void RefreshParticlePAndV(){ for (int i = 0; i < g_nPopulationNum; i++) { /* X方向速度(如果是多维的话,这里指第一维的速度) */ double dRand1 = (double)rand() / RAND_MAX; /* 取0到1之间的随机数 */ double dRand2 = (double)rand() / RAND_MAX; g_astParticles[i].dVX = g_astParticles[i].dVX + g_dC1 * dRand1 * (g_astPBestParticle[i].dX - g_astParticles[i].dX) + g_dC2 * dRand2 * (g_stGBestParticle.dX - g_astParticles[i].dX); /* Y方向速度(如果是多维的话,这里指第一维的速度) */ dRand1 = (double)rand() / RAND_MAX; dRand2 = (double)rand() / RAND_MAX; g_astParticles[i].dVY = g_astParticles[i].dVY + g_dC1 * dRand1 * (g_astPBestParticle[i].dY - g_astParticles[i].dY) + g_dC2 * dRand2 * (g_stGBestParticle.dY - g_astParticles[i].dY); /* 如果速度超过边界,则设为边界 */ if (g_astParticles[i].dVX < g_dVMin) { g_astParticles[i].dVX = g_dVMin; } if (g_astParticles[i].dVX > g_dVMax) { g_astParticles[i].dVX = g_dVMax; } if (g_astParticles[i].dVY < g_dVMin) { g_astParticles[i].dVY = g_dVMin; } if (g_astParticles[i].dVY > g_dVMax) { g_astParticles[i].dVY = g_dVMax; } /* 粒子位置更新 */ g_astParticles[i].dX = g_astParticles[i].dX + g_astParticles[i].dVX; g_astParticles[i].dY = g_astParticles[i].dY + g_astParticles[i].dVY; if (g_astParticles[i].dX > g_nXMax) { g_astParticles[i].dX = g_nXMax; } if (g_astParticles[i].dX < g_nXMin) { g_astParticles[i].dX = g_nXMin; } if (g_astParticles[i].dY > g_nYMax) { g_astParticles[i].dY = g_nYMax; } if (g_astParticles[i].dY < g_nYMin) { g_astParticles[i].dY = g_nYMin; } }}void main(){ clock_t start, finish; start = clock(); srand((unsigned)time(NULL)); Initialization(); for (int i = 0; i < g_nG; i++) { /* 计算每个粒子的适应度值 */ CalFitness(); /* 找到每个粒子各自的极值,以及整体的极值 */ SearchPGBestParticle(); /* 更新粒子的位置和速度 */ RefreshParticlePAndV(); printf("第%d代,最优值位置为(%f, %f),最优值为:%f\n", i + 1, g_stGBestParticle.dX, g_stGBestParticle.dY, g_stGBestParticle.dFitness); } finish = clock(); double dTimeSpan = (double)(finish - start) / CLOCKS_PER_SEC; printf("程序运行时间:%f\n", dTimeSpan); system("pause"); return;}
运行结果
从运行结果可以看出,当迭代到54代时就达到了最大值。每次运行的结果可能不一样。
粒子群算法和遗传算法的流程比较像,粒子群算法需要重点关注速度更新公式:
参考资料
https://blog.csdn.net/hcc199521/article/details/53445656?utm_medium=distribute.pc_relevant.none-task-blog-title-2&spm=1001.2101.3001.4242
(注:本文内容仅供学习交流,如有资料涉及侵权,请通知我删除。谢谢!)