C语言实现粒子群算法

C语言实现粒子群算法

一、粒子群算法介绍

  粒子群算法是一种进化算法,其思想来源是模仿自然界中的鸟类觅食。

  假设有50只鸟随机出现在一个位置,并且他们有随机的初始速度,假设单位时间内初始速度不变,单位时间后,他们会到达一个新的位置,并且会判断自己这个位置的好坏程度(可以理解成离食物的远近),其他的鸟儿下一次选择速度的时候会学习在好坏程度上的自己的历史最优位置和所有鸟的历史最优位置,调整自己的速度,然后重复上述过程,直到轮次结束。

  我们可以用这种思想来寻找全局最优解,假设我们要找一个二维函数f(x,y)的最小值,(x,y)∈D,我们可以先生成50个粒子,他们有随机的初始二维坐标,然后随机生成50个粒子的初始速度,然后经过单位时间后,50个粒子到达了新的位置,计算他们在这个位置的函数值,然后把自己的值放到局部最优里,把所有值中最小的值对应的粒子的信息(位置,坐标,值)放到全局最优数组里。

  接下来的每一轮行为都是相似的,利用循环完成:根据到上一轮以前的全局最优和自己的历史最优和自己上一轮的速度调整自己的速度,然后再求值,再放到局部最优数组的第t个位置里,然后对局部最优数组求最小值放到局部最优数组的第t个位置,然后求此轮全局的最小值,然后比较过往的全局最小值和此轮全局最小值,取较小者放到全局最小值数组的第t个位置中。

  最后,当t大于循环轮次的时候,跳出循环,输出全局最小值数组中的第t-1个位置。

  负责速度更新的式子可以这样写。
v i ( t ) ⃗ = α v i ( t − 1 ) ⃗ + β ( j u b u i ⃗ ( t − 1 ) − r i ⃗ ( t − 1 ) ) + γ ( q u a n j u ⃗ ( t − 1 ) − r i ⃗ ( t − 1 ) ) \vec{v_{i}(t)}=\alpha\vec{v_{i}(t-1)}+\beta(\vec{jubu_{i}}(t-1)-\vec{r_{i}}(t-1))+\gamma(\vec{quanju}(t-1)-\vec{r_{i}}(t-1)) vi(t) =αvi(t1) +β(jubui (t1)ri (t1))+γ(quanju (t1)ri (t1))
  其中,a是表示之前速度对这次速度选择的影响程度(惯性)的参数,b表示历史最优位置对这次速度选择的影响程度的参数,y是表示历史全局最优对这次速度选择影响程度的参数,vi(t)表示i粒子第t轮的速度,jubui(t-1)表示i粒子第t-1轮以前的历史最优位置,quanjui(t-1)表示t到t-1轮为止的全局最优位置,ri(t-1)表示i粒子第t-1轮的位置。

  负责位置更新的式子可以这样写
r i ⃗ ( t ) = r i ⃗ ( t − 1 ) + v ⃗ i ( t ) \vec{r_i}(t)=\vec{r_i}(t-1)+\vec{v}_i(t) ri (t)=ri (t1)+v i(t)

二、C语言实现粒子群算法
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define EPS 1e-9
typedef struct {
	double x;
	double y;
}Point;
//二维函数,点是二维坐标。

typedef struct {
	Point point;
	double z;
}Abird;
//Abird结构体存放粒子的点和对应函数值的信息

typedef struct {
	Abird a[500];
}zuiyou;
//局部最优则建立一个zuiyou数组,全局最优建立一个zuiyou就可
//这里的500代表会放500个轮次的全局最优进去,所以500是轮次数。

double f(double x, double y)//目标函数
{
	//return 2 * x * x * x + 3 * y * y * y + 4 * x * y * y - 5 * x * x * y + 10;
	return 2 * x * x + 3 * y * y + 4 * x * y;
}


Abird mymin(Abird bird[], int sz)//选择Abird作为返回值目的是返回整个带有完整信息(点,值)的最小值。
{
	Abird ret = bird[0];
	for (int i = 0; i < sz; i++)
	{
		if (ret.z - bird[i].z > EPS && bird[i].point.x - 0.0 > EPS && 5.0 - bird[i].point.x > EPS && bird[i].point.y - 3.0 > EPS && 5.0 - bird[i].point.y > EPS)
        //控制粒子不要飞出界,飞出界的粒子我们就舍弃了
		{
			ret = bird[i];
		}
	}
	return ret;
}





int main()
{
	Abird bird[50] = { 0 };//50只鸟
	zuiyou jubu[50] = { 0 };//jubu[i].a[t]表示i鸟第t轮的局部最优
	zuiyou quanju = { 0 };//quanju.a[t]表示第t轮的全局最优
	Point v[50] = { 0 };//50只鸟速度矢量的创建
	srand((unsigned)time(NULL));//随机种子
	for (int i = 0; i < 50; i++)
	{
		bird[i].point.x = 0.0 + 1.0 * (rand() % RAND_MAX) / RAND_MAX * (5.0 - 0.0);
		bird[i].point.y = 3.0 + 1.0 * (rand() % RAND_MAX) / RAND_MAX * (5.0 - 3.0);
		v[i].x = 0.0 + 0.1 * (rand() % RAND_MAX) / RAND_MAX * (0.1 - 0.0);
		v[i].y = 0.0 + 0.1 * (rand() % RAND_MAX) / RAND_MAX * (0.1 - 0.0);
	}//初始化50个粒子的速度和位置。
//随机生成[x, y)的浮点数,x + 1.0 * ( rand() % RAND_MAX ) / RAND_MAX * ( y - x )
//随机生成[x,y]的浮点数,x + 1.0 * rand() / RAND_MAX * ( y - x )

	for (int i = 0; i < 50; i++)
	{
		bird[i].point.x += v[i].x;
		bird[i].point.y += v[i].y;
		bird[i].z = f(bird[i].point.x, bird[i].point.y);
		jubu[i].a[0] = bird[i];//第0轮的局部最优就是这次的位置
	}
	quanju.a[0] = mymin(bird, 50);
    //第0轮的全局最优
	int t = 1;
	while (t < 500)//进行499轮
	{
		for (int i = 0; i < 50; i++)
		{
            //更新速度
			v[i].x = 0.5 * v[i].x + 0.2 *  (jubu[i].a[t - 1].point.x - bird[i].point.x) + 0.3 *  (quanju.a[t - 1].point.x - bird[i].point.x);
			v[i].y = 0.5 * v[i].y + 0.2 *  (jubu[i].a[t - 1].point.y - bird[i].point.y) + 0.3 *  (quanju.a[t - 1].point.y - bird[i].point.y);
            //更新位置
			bird[i].point.x += v[i].x;
			bird[i].point.y += v[i].y;
			if (bird[i].point.x - 0.0 > EPS && 5.0 - bird[i].point.x > EPS && bird[i].point.y - 3.0 > EPS && 5.0 - bird[i].point.y > EPS)
             //保证经过第t轮后出界的粒子被舍弃
			{
				bird[i].z = f(bird[i].point.x, bird[i].point.y);
			}
			else
			{
				bird[i].z = 100000.0;
			}
			jubu[i].a[t] = bird[i];//先把此次的局部最优储存起来
			jubu[i].a[t] = mymin(jubu[i].a, t + 1);//与历史过往的局部最优比较
		}
		quanju.a[t] = mymin(bird, 50);//求第t轮的全局最优
		if (quanju.a[t].z - quanju.a[t - 1].z > EPS)
		{
			quanju.a[t] = quanju.a[t - 1];
		}//与上一轮的全局最优相比,若比上一轮差则交换。
		t++;
	}

	printf("粒子群算法的解是%lf,对应坐标为(%lf,%lf)", quanju.a[t - 1].z, quanju.a[t - 1].point.x, quanju.a[t - 1].point.y);
	return 0;
}
  • 11
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
粒子群算法是一种优化算法,可以用于求解函数的最小值。下面是C语言实现粒子群算法的步骤: 1. 定义粒子结构体,包括位置、速度、历史最优位置和历史最优值等信息。 2. 初始化粒子群,包括生成随机位置和速度等信息。 3. 迭代更新粒子位置和速度,根据粒子的历史最优位置和全局最优位置来更新速度,再根据速度更新位置。 4. 计算每个粒子的函数值,并更新历史最优位置和全局最优位置。 5. 判断是否达到停止条件,如果没有则返回第3步,否则输出全局最优位置和值。 下面是一个简单的C语言实现粒子群算法的代码示例: ``` #include <stdio.h> #include <stdlib.h> #include <math.h> #define N 50 // 粒子数 #define D 2 // 维度 #define MAX_ITER 100 // 最大迭代次数 #define w 0.8 // 惯性权重 #define c1 2 // 自我认知因子 #define c2 2 // 社会认知因子 typedef struct { double x[D]; // 位置 double v[D]; // 速度 double p[D]; // 历史最优位置 double fp; // 历史最优值 } Particle; double f(double x[], int d) { // 待优化的函数 double sum = 0; for (int i = 0; i < d; i++) { sum += x[i] * x[i]; } return sum; } void init(Particle particles[]) { // 初始化粒子群 for (int i = 0; i < N; i++) { for (int j = 0; j < D; j++) { particles[i].x[j] = (double)rand() / RAND_MAX * 10 - 5; // 位置随机生成在[-5, 5]之间 particles[i].v[j] = (double)rand() / RAND_MAX * 2 - 1; // 速度随机生成在[-1, 1]之间 particles[i].p[j] = particles[i].x[j]; // 初始历史最优位置为当前位置 } particles[i].fp = f(particles[i].p, D); // 计算历史最优值 } } void update(Particle particles[], double gbest[]) { // 更新粒子位置和速度 for (int i = 0; i < N; i++) { for (int j = 0; j < D; j++) { double r1 = (double)rand() / RAND_MAX; double r2 = (double)rand() / RAND_MAX; particles[i].v[j] = w * particles[i].v[j] + c1 * r1 * (particles[i].p[j] - particles[i].x[j]) + c2 * r2 * (gbest[j] - particles[i].x[j]); // 更新速度 particles[i].x[j] += particles[i].v[j]; // 更新位置 } double fp = f(particles[i].x, D); // 计算当前位置的函数值 if (fp < particles[i].fp) { // 更新历史最优位置和值 particles[i].fp = fp; for (int j = 0; j < D; j++) { particles[i].p[j] = particles[i].x[j]; } } } } void pso() { Particle particles[N]; double gbest[D]; // 全局最优位置 double fgbest = INFINITY; // 全局最优值 init(particles); // 初始化粒子群 for (int t = 0; t < MAX_ITER; t++) { // 迭代更新 for (int i = 0; i < N; i++) { if (particles[i].fp < fgbest) { // 更新全局最优位置和值 fgbest = particles[i].fp; for (int j = 0; j < D; j++) { gbest[j] = particles[i].p[j]; } } } update(particles, gbest); // 更新粒子位置和速度 } printf("Global best position: (%f, %f)\n", gbest[0], gbest[1]); printf("Global best value: %f\n", fgbest); } int main() { srand(0); pso(); return 0; } ```
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值