烟花算法初探

前沿:函数优化求解问题学习过程中,不可避免选择求解算法,且不同的算法收敛速度不同,复杂度不同。探究问题求解的性能,则需要对求解算法进行对比。因此,在这里,引入烟花算法。

以下资料来源于书籍:《烟花算法引论》谭营 著;科学出版社,2015

1.烟花算法介绍

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.算法组成

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.算法实现

3.1 随机维度选择
随机维度选择是指在1和dim之间随机选择n个维度,且n个维度不重复。作用是在进行位移操作时对指定数量的位置进行偏移,即产生新的爆炸火花。
过程实现如下:

void DimensionRand(int dim, int num) {//num表示需要产生的维度个数
	for (int i = 0; i < dim; ++i) set_rand[i] = i;
	for (int j = dim - 1; j >= 1; --j) swap(set_rand[j], set_rand[rand() % j]);
}

3.2 爆炸算子
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
实现过程如下:

void Explosion() {
	//计算烟花适应度值
	for (int i = 0; i < fire_num; i++) {
		fitness[i] = Fitness(x_loc, i);
	}
	/*cout<<endl << "适应值:"<<endl;
	for (int i = 0; i < fire_num; i++) {
		cout << fitness[i] << " ";
	}*/

	//查询当前最优和最坏烟花个体
	fit_bad = fitness[0];
	fit_bad_index = 0;
	fit_best = fitness[0];
	fit_best_index = 0;
	for (int i = 0; i < fire_num;i++) {
		if (fitness[i] > fit_bad) {//查询最坏值
			fit_bad = fitness[i];
			fit_bad_index = i;
		}
		if (fitness[i] < fit_best) {//查询最坏值
			fit_best = fitness[i];
			fit_best_index = i;
		}
	}
	//cout << endl << "最坏值:" << fit_bad << endl<<"最好值:"<< fit_best<<endl;

	//计算火花个数
	double S_tem=0;
	for (int i = 0; i < fire_num;i++) {//计算分母
		S_tem += fit_bad - fitness[i];
	}
	for (int i = 0; i < fire_num;i++) {//计算火花数
		S_num[i] = fire_all * (fit_bad - fitness[i] + SMALL) / (S_tem+SMALL);
	}
	//cout <<endl<< "火花数:" << endl;for (int i = 0; i < fire_num; i++) {cout<<S_num[i] << " ";}
	for (int i = 0; i < fire_num; i++) {//火花数限制取整
		if (S_num[i] < a*fire_all) 
			S_num[i] = round(a*fire_all);
		else if(S_num[i] > b*fire_all)
			S_num[i] = round(b*fire_all);
		else
			S_num[i] = round(S_num[i]);		
	}
	//cout <<endl<< "修正火花数:" << endl;for (int i = 0; i < fire_num; i++) {cout << S_num[i] << " ";}
	 
	//计算爆炸半径
	double A_tem = 0;
	for (int i = 0; i < fire_num; i++) {//计算分母
		A_tem += fitness[i]- fit_best;
	}
	for (int i = 0; i < fire_num; i++) {//计算火花数
		A_radius[i] = (int(10000*A_all * ( fitness[i]- fit_best + SMALL) / (A_tem + SMALL)))/10000.0;
	}
	srand((unsigned)time(NULL));
	for (int i = 0; i < fire_num;i++) {
		for (int k = 0; k < dim_num;k++) {//初始化维度集合
			set_rand[k] = -1;
		}
		srand((unsigned)time(NULL));
		for (int j = 0; j < S_num[i];j++) {
			DimensionRand(dim_num, set_num1);
			for (int k = 0; k < dim_num; k++) {
				if (k >= set_num1)
					set_rand[k] = -1;	
			}
			for (int k = 0; k < dim_num; k++) {
				spark[i][j][k] = x_loc[i][k];
			}
			for (int k = 0; k <set_num1; k++) {
				//计算位移
				h_offset = UniformDistribution(0.0,A_radius[i]);
				spark[i][j][set_rand[k]] = x_loc[i][set_rand[k]]+ h_offset;
				Mapping(spark,i,j, set_rand[k]);
			}
			
		}
	}
}

3.3 映射规则
产生的火花以及子代难免出现超出界限的情况,这时需要对界限进行操作;一种方法是:若位置超出界限,则重新随机生成;另一种方法是:若位置超出界限,则将其映射到界限以内。烟花算法则使用第二种方法。
在这里插入图片描述

void Mapping(double x1[fire_num][fire_all][dim_num], int fire, int S, int dim_k) {//输入位置集合、指定烟花和维度位置
	if (x1[fire][S][dim_k] != x_min * 10) {
		if ((x1[fire][S][dim_k] < x_min) || (x1[fire][S][dim_k] > x_max)) {
			double a1 = fabs(x1[fire][S][dim_k]);
			int a12 = int(a1 * 1000);
			double b1 = x_max - x_min;
			int b12 = int(b1 * 1000);
			x1[fire][S][dim_k] = x_min + double(a12 % b12) / 1000.0;
		}
	}
}

3.4 变异算子
在这里插入图片描述
在这里插入图片描述
实现过程如下:

void Mutation() {
	//产生变异位置
	for (int k = 0; k < dim_num; k++) {//初始化维度集合
		set_rand[k] = -1;
	}
	srand((unsigned)time(0));
	for (int i = 0; i < fire_num;i++) {
		srand((unsigned)time(0));
		for (int j = 0; j < S_num[i];j++) {
			//产生变异维度
			DimensionRand(dim_num, set_num2);
			for (int q = 0; q < dim_num; q++) {
				if (q >= set_num2)
					set_rand[q] = -1;
			}
			for (int k = 0; k < set_num2;k++) {
				spark[i][j][set_rand[k]] = spark[i][j][set_rand[k]] * GaussianRand(1, 1);
				Mapping(spark,i,j, set_rand[k]);//映射
			}
		}
	}
}

3.5 选择策略
在这里插入图片描述
选择策略的作用是产生新一代个体,引论中选择轮盘赌算法进行选择。在这里偷个懒,使用精英保留策略产生子代,即从烟花和火花中选择最好的个体烟花或者火花成为子代。
实现过程如下:

void Select() {
	double fit_tem1[fire_num];
	int fit_index_tem1[fire_num];
	double fit_tem2[fire_num][fire_all];
	int fit_index_tem2[fire_num][fire_all];
	//初始化
	for (int i = 0; i < fire_num;i++) {
		fit_tem1[i] = -1;
		fit_index_tem1[i] = i;
		for (int j = 0; j < fire_all;j++) {
			fit_tem2[i][j] = -1;
			fit_index_tem2[i][j] = j;
		}
	}
	//计算适应值
	for (int i = 0; i < fire_num;i++) {
		fit_tem1[i] = Fitness(x_loc,i);
		for (int j = 0; j < S_num[i];j++) {
			fit_tem2[i][j] = Fitness(spark[i],j);
		}
	}
	//适应值排序:由小到大->冒泡排序
	for (int i = 1; i < fire_num; i++) {
		for (int j = 0; j < fire_num - i; j++) {
			if (fit_tem1[j + 1] < fit_tem1[j]) {
				double compare_tem = fit_tem1[j];
				int count_tem = fit_index_tem1[j];
				fit_tem1[j] = fit_tem1[j + 1];
				fit_index_tem1[j] = fit_index_tem1[j+1];
				fit_tem1[j + 1] = compare_tem;
				fit_index_tem1[j + 1] = count_tem;
			}
		}
	}
	for (int i = 0; i < fire_num;i++) {
		for (int k = 1; k < S_num[i]; k++) {
			for (int j = 0; j < S_num[i] - k; j++) {
				if (fit_tem2[i][j] != -1) {
					if (fit_tem2[i][j + 1] < fit_tem2[i][j]) {
						double compare_tem = fit_tem2[i][j];
						int count_tem = fit_index_tem2[i][j];
						fit_tem2[i][j] = fit_tem2[i][j + 1];
						fit_index_tem2[i][j] = fit_index_tem2[i][j + 1];
						fit_tem2[i][j + 1] = compare_tem;
						fit_index_tem2[i][j + 1] = count_tem;
					}
				}
			}
		}
	}
	for (int i = 0; i < fire_num;i++) {
		int index_select = -1;
		double fit_select = fit_tem1[i];
		if (fit_select > fit_tem2[i][0]) {
			fit_select = fit_tem2[i][0];
			index_select = fit_index_tem2[i][0];
		}
		for (int k = 0; k < dim_num; k++) {
			if (fit_select != fit_tem1[i]) {
				x_loc[i][k] = spark[i][index_select][k];
			}			
		}
	}
}

经测试,对应问题结果无限趋近于最优值。

结语:引论中提供了大量的函数测试集,便于对算法进行测试。
此外,烟花算法提出时间较短,还存在大量的研究缺口以及改进措施,引论中也有相应描述。

  • 13
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南音小榭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值