萤火虫算法
作者:Xin-She Yang
萤火虫算法是一种基于自然界中萤火虫的求解算法。这种算法以萤火虫的生物特性为基础,模拟萤火虫在食物、繁殖等方面的行为,解决优化问题。在萤火虫算法中,萤火虫会根据其亮度和距离因素移动,以寻找最优解。通过多次迭代,萤火虫算法可以逐渐优化解决方案,找到全局最优解或局部最优解。与其他常用的优化算法相比,萤火虫算法具有更快的收敛速度和更高的精度。
亮度
首先是亮度,对于每个萤火虫个体来说,他看到别人的亮度取决于别人的亮度,介质的吸光性,以及距离。而别人的亮度,在最大值问题里面和正相关,在最小值问题里面负相关。
由于计算这个看到别人的亮度,需要指数运算很耗时,所以可以优化成下面的样子,这样就不需要指数级运算了。
在很近的距离的时候,这两个公式是等价的,我们可以在r = 0的时候泰勒展开看出,所以可以直接替换减少运算时间。
吸引力
因为光强和吸引力成正比所以我们对于吸引力,,我们也可以通过这个方式进行计算。
距离rij
这里,论文给出了欧氏距离作为一个距离的例子,直接计算两个萤火虫i,j的坐标的距离,当然,处理别的问题的时候距离可以使用别的指标,例如调度问题里面的成本花费,或者是时间什么的。
移动公式
最后的算法主体流程
Firefly Algorithm
Objective function
Generate initial population of fireflies
Light inlensily al is determined by
Define light absorption coefficient
while ( MaxGeneration)
for all fireflies
for all fireflies
if , Move firefly towards in -dimension; end if Attractiveness varies with distance via
Evaluate new solulions and update light intensily end for
end for
Rank the fireflies and find the current best
end while
Postprocess results and visualization
JAVA代码实现
package Singal;
//Firefly Algorithms for Multimodal Optimization
import java.util.ArrayList;
import java.util.List;
public class FA {
Individual.FitnessCultor fitnessCultor = null;
int popSize = 50;//种群大小
double ub = 4;//按论文的图里面的上下限
double lb = 0;//下界
int dim = 2;//维度
int maxIterTime = 50;//最大迭代次数
Individual bestFly = null;//
public FA(Individual.FitnessCultor fitnessCultor){
this.fitnessCultor = fitnessCultor;
List<Individual> pop = init(popSize,dim,ub,lb);
int curIterTime = 0;
double beta0 = 1;// r = 0 时候的初始吸引力
double gama = 1;//介质吸收
double alpha = 0.2;//移动幅度
while(curIterTime<maxIterTime){
for (int i = 0; i < popSize; i++) {
for (int j = 0; j < i; j++) {//这里到i是因为上一轮迭代已经排序过了,后面没必要遍历了。O(n^2)->O(NLogN)
Individual a = pop.get(i);
Individual b = pop.get(j);
if(a.fitness>b.fitness){//因为Michalewicz是求解最小值问题,所以是越小越好,这里直接将光强=适应度值。
double distance = culDistance(a.getPosition(),b.getPosition());
double attraction = beta0*Math.exp(-gama*distance*distance);
Position ap = a.getPosition();
Position bp = a.getPosition();
for (int k = 0; k < ap.size(); k++) {
ap.set(k,ap.get(k)+attraction*(bp.get(k)-ap.get(k))+alpha*(Math.random()*0.5));
}
updateFitness(a);
}
}
}
pop.sort((a,b)->(new Double(a.getFitness()).compareTo(b.getFitness())));//小号优先
if(bestFly==null||bestFly.fitness>pop.get(0).fitness){
bestFly = pop.get(0).clone();
}
System.out.println(bestFly.getFitness());
curIterTime++;
}
}
/**
*
* @param popSize 种群大小
* @param dim 位置的维度
* @param ub 每个维度的上限,为了偷懒都一样好了
* @param lb 每个维度的下限,
* @return
*/
public List<Individual> init(int popSize,int dim,double ub,double lb){
List<Individual> pop = new ArrayList<>();
PositionFactory positionFactory = new PositionFactory(dim,ub,lb);
for (int i = 0; i < popSize; i++) {
Individual ind = new Individual(positionFactory.initRandomPosition());
updateFitness(ind);
pop.add(ind);
}
return pop;
}
public void updateFitness(Individual individual){
individual.fitness = fitnessCultor.culFitness(individual);
}
public static void main(String arg[]){
new FA(new Individual.FitnessCultor() {
@Override
public double culFitness(Individual i) {
return Michalewicz(i.getPosition());
}
});
}
//计算适应度值
public static double Michalewicz(Position position){
double res = 0;
double m = 10;
for (int i = 0; i < position.size(); i++) {
double x = position.get(i);
res+=-Math.sin(x)*Math.pow(Math.sin((i+1)*x*x/Math.PI),2*m);
}
return res;
}
//计算欧氏距离
public static double culDistance(Position a,Position b){
double res = 0;
for (int i = 0; i < a.size(); i++) {
double x1 = a.get(i);
double x2 = b.get(i);
res+=(x1-x2)*(x1-x2);
}
res = Math.sqrt(res);
return res;
}
}
conclusion
这篇论文最大的亮点就是将pso一般化,并且给出了优化了计算,将指数运算变成除法运算,同时这篇论文的距离也可以做很多的扩展性修改。