人工蜂群算法(ABC算法)(Artificial Bee Colony)
Java实现测试函数Rastrigin,附上原型代码翻译后的注释。
题目:
待优化问题参数设置10个,运行一次,[-5.12,5.12]。
附上代码:
package ABCtest;public class bee {/* ABC算法的控制参数 */int NP=20; /* 蜂群大小(雇佣蜂+观蜜蜂) (employed bees+onlooker bees)*/int FoodNumber = NP/2; /*食物源的数量相当于蜂群数量的一半*/int limit = 100; /*一种无法通过“限制”改善的食物源被其雇佣蜂抛弃*/int maxCycle = 2500; /*觅食循环次数{一个停止条件}*//* 问题的特殊变量*/int D = 10; /*待优化问题的参数个数*/double lb = -5.12; /*参数的下界。*/double ub = 5.12; /*参数的上界。对于参数有不同边界的问题,可以将lb和ub定义为数组*/double Foods[][]=new double[FoodNumber][D]; /*foods是食物源的数组。每一行是一个包含D个待优化参数的向量。矩阵的行数等于食物源数*/double f[]=new double[FoodNumber]; /*f是一个与食物源相关的目标函数值的数组*/double fitness[]=new double[FoodNumber]; /*fitness是与食物源相关的质量值的数组*/double trial[]=new double[FoodNumber]; /*trial is a vector holding trial numbers through which solutions can not be improved*/double prob[]=new double[FoodNumber]; /*prob表示食物源被选择的概率的数组*/double solution[]=new double[D];double ObjValSol; /*Objective function value of new solution*/double FitnessSol; /* Fitness value of new solution*/int neighbour, param2change; /*param2change corrresponds to j, neighbour corresponds to k in equation v_{ij}=x_{ij}+\phi_{ij}*(x_{kj}-x_{ij})*/double GlobalMin; /*ABC算法求得的最优解*/double GlobalParams[]=new double[D]; /*最优解的参数Parameters of the optimum solution*/double r; /* [0,1)的随机数 *//*适应度函数*/double CalculateFitness(double fun){double result=0;if(fun>=0){result=1/(fun+1);}else{result=1+Math.abs(fun);}return result;}/*记录最优解*/void MemorizeBestSource(){int i,j;for(i=0;i<FoodNumber;i++){if (f[i]<GlobalMin){GlobalMin=f[i];for(j=0;j<D;j++)GlobalParams[j]=Foods[i][j];}}}/* 变量在[lb,ub]范围内初始化。如果每个参数的取值范围不同,使用lb[j]、ub[j]数组代替lb和ub *//* 食物源的计数器也在这个函数中初始化*/void init(int index){int j;for (j=0;j<D;j++){r = ( (double)Math.random()*32767 / ((double)32767+(double)(1)) );Foods[index][j]=r*(ub-lb)+lb;solution[j]=Foods[index][j];}f[index]=calculateFunction(solution);fitness[index]=CalculateFitness(f[index]);trial[index]=0;}/*初始化所有食物源 */void initial(){int i;for(i=0;i<FoodNumber;i++){init(i);}GlobalMin=f[0];for(i=0;i<D;i++)GlobalParams[i]=Foods[0][i];}void SendEmployedBees(){int i,j;/*雇佣蜂阶段*/for (i=0;i<FoodNumber;i++){/*随机更改参数*/r = ((double) Math.random()*32767 / ((double)(32767)+(double)(1)) );param2change=(int)(r*D);/*使用随机数产生不同的解*/r = ( (double)Math.random()*32767 / ((double)(32767)+(double)(1)) );neighbour=(int)(r*FoodNumber);for(j=0;j<D;j++)solution[j]=Foods[i][j];r = ( (double)Math.random()*32767 / ((double)(32767)+(double)(1)) );solution[param2change]=Foods[i][param2change]+(Foods[i][param2change]-Foods[neighbour][param2change])*(r-0.5)*2;/*如果超出边界,则直接等于边界*/if (solution[param2change]<lb)solution[param2change]=lb;if (solution[param2change]>ub)solution[param2change]=ub;ObjValSol=calculateFunction(solution);FitnessSol=CalculateFitness(ObjValSol);/*贪婪选择一下*/if (FitnessSol>fitness[i]){/*如果变换后的解优于原解,则替换之,并重置计数器*/trial[i]=0;for(j=0;j<D;j++)Foods[i][j]=solution[j];f[i]=ObjValSol;fitness[i]=FitnessSol;}else{ /*如果解决方案没有改进,增加它的试验次数*/trial[i]=trial[i]+1;}}/*雇佣蜂阶段结束*/}/*选择食物源的概率与其质量成正比*//*可以采用多种方案来计算概率值*//*例如 prob(i)=fitness(i)/sum(fitness) *//*或者 prob(i)=a*fitness(i)/max(fitness)+b*//*概率值由适应度值计算,并除以最大适应度值来标准化*/void CalculateProbabilities(){int i;double maxfit;maxfit=fitness[0];for (i=1;i<FoodNumber;i++){if (fitness[i]>maxfit)maxfit=fitness[i];}for (i=0;i<FoodNumber;i++){prob[i]=(0.9*(fitness[i]/maxfit))+0.1;}}void SendOnlookerBees(){int i,j,t;i=0;t=0;/*观察蜂阶段*/while(t<FoodNumber){r = ( (double)Math.random()*32767 / ((double)(32767)+(double)(1)) );if(r<prob[i]) /*根据选择概率选择食物源*/{t++;/*随机更改参数*/r = ((double)Math.random()*32767 / ((double)(32767)+(double)(1)) );param2change=(int)(r*D);/*使用随机数产生不同的解*/r = ( (double)Math.random()*32767 / ((double)(32767)+(double)(1)) );neighbour=(int)(r*FoodNumber);/*随机解必须不同于解i*/while(neighbour == i){r = ( (double)Math.random()*32767 / ((double)(32767)+(double)(1)) );neighbour=(int)(r*FoodNumber);}for(j=0;j<D;j++)solution[j]=Foods[i][j];r = ( (double)Math.random()*32767 / ((double)(32767)+(double)(1)) );solution[param2change]=Foods[i][param2change]+(Foods[i][param2change]-Foods[neighbour][param2change])*(r-0.5)*2;/*如果超出边界,则直接等于边界*/if (solution[param2change]<lb)solution[param2change]=lb;if (solution[param2change]>ub)solution[param2change]=ub;ObjValSol=calculateFunction(solution);FitnessSol=CalculateFitness(ObjValSol);/*贪婪选择一下*/if (FitnessSol>fitness[i]){trial[i]=0;for(j=0;j<D;j++)Foods[i][j]=solution[j];f[i]=ObjValSol;fitness[i]=FitnessSol;}else{ /*如果解决方案没有改进,增加它的试验次数*/trial[i]=trial[i]+1;}}i++;if (i==FoodNumber-1)i=0;}/*观察蜂阶段结束 */}/*确定哪些食物源的试验计数器超过了“limit”值. 在基本的ABC算法中,每次循环只允许有一个侦察蜂*/void SendScoutBees(){int maxtrialindex,i;maxtrialindex=0;for (i=1;i<FoodNumber;i++){if (trial[i]>trial[maxtrialindex])maxtrialindex=i;}if(trial[maxtrialindex]>=limit){init(maxtrialindex);}}double calculateFunction(double sol[]){return Rastrigin (sol);}double Rastrigin(double sol[]){int j;double top=0;for(j=0;j<D;j++){top=top+(Math.pow(sol[j],(double)2)-10*Math.cos(2*Math.PI*sol[j])+10);}return top;}public static void main(String[] args) {bee bee=new bee();int iter=0;int j=0;bee.initial(); /*初始化所有食物源 */bee.MemorizeBestSource(); /*记录最优解*/for (iter=0;iter<bee.maxCycle;iter++){bee.SendEmployedBees(); /*雇佣蜂阶段*/bee.CalculateProbabilities(); /*计算食物源适应度*/bee.SendOnlookerBees(); /*观察蜂阶段*/bee.MemorizeBestSource(); /*记录最优解*/bee.SendScoutBees(); /*侦查蜂阶段*/}for(j=0;j<bee.D;j++) /*循环打印10个最优解的参数*/{System.out.println("最优解的参数GlobalParam["+(j+1)+"]:"+bee.GlobalParams[j]);}System.out.println("最优解为:"+bee.GlobalMin); /*打印每次运行的最优解*/}
}
运行截图: