求下述二元函数的最大值:
下参考Mitchell《机器学习》中的遗传算法解决上面问题的java代码如下:
import java.lang.Math; import java.util.ArrayList; import java.util.List; /** * 采用遗传算法求下列二元函数的最大值 * max f(x1,x2)=x1^2+x2^2; * s.t.x1∈{1,2,3,4,5,6,7};x2∈{1,2,3,4,5,6,7}; */ public class GAFunBVar { private int x1,x2; private int groupSize;//群体尺寸 private String[] group;//群体 private double r;//每一步通过交叉取代群体成员的比例 private double m;//变异率 private String maxFitEntity;//最大适应度个体 private int maxFitness;//保存最大适应度 private final int SWAPSIZE=100; private int noSwapNum=0;//最大适应度未交换次数,当该值大于某个SWAPSIZE,算法结束,付出最大适应度和满足的个体 private double[] pr; private String[] thrbin={"000","001","010","011","100","101","110","111"}; private static final int GENERATION=50;//进化多少代后停止。 public GAFunBVar(int x1,int x2,int groupSize,double r,double m) { this.x1=x1; this.x2=x2; this.groupSize=groupSize; group=new String[groupSize]; this.r=r; this.m=m; pr=new double[groupSize]; } /* * 编码 * @x1,x2 要编码的两个十进制数 * @binStr 返回的二进制串 */ private String coding(int x1,int x2) { return thrbin[x1]+thrbin[x2]; } /* * 解码 * @binStr 要解码的二进制串 * @int[] x 保存解码出来的两个十进制数 */ private int[] enCoding(String binStr) { int[] x=new int[2]; String x1Str=binStr.substring(0,3); String x2Str=binStr.substring(3); for(int i=0;i<thrbin.length;i++) { if(x1Str.equals(thrbin[i])) x[0]=i; if(x2Str.equals(thrbin[i])) x[1]=i; } return x; } /* * 初始群体产生 */ private void InitGroup() { int i,m; String[] temp=new String[groupSize];//为了产生不重复的个体,设置的临时群体 for(int j=0;j<groupSize;j++) temp[j]=null; for(i=0;i<groupSize;i++) { group[i]=thrbin[(int)(7*Math.random())+1]+thrbin[(int)(7*Math.random())+1]; for(m=0;m<i;m++) { if(group[i].equals(temp[m]))//如果这个个体已经被选择,则对第i个个体重新随机选择 { i--; break; } } if(m==i)//说明该个体第一次选择,加入临时群体 temp[i]=group[i]; } } /* * 适应度计算 */ private int countFitness(String entityStr) { int[] x=new int[2]; x=enCoding(entityStr); return x[0]*x[0]+x[1]*x[1]; } /* * 整个群体的每个个体适应度计算,并和最大适应度比较,选出新的最大适应度,及相应的个体 * @group 群体 * @fitness 群体对应的适应度 */ private void getMaxFitness(String[] group) { int[] fitness=new int[groupSize];//每个个体对应的适应度 int flag=0;//标记交换情况 for(int i=0;i<groupSize;i++) { fitness[i]=countFitness(group[i]); if(fitness[i]>maxFitness) { flag=1; maxFitness=fitness[i]; maxFitEntity=group[i]; noSwapNum=0; } } if(flag==0) { noSwapNum++; } } /* * 选择(),在此之前要进行假设被选择的概率的计算 * @rnewEntNum 要选择的成员个数 */ private void chooseNewEnt(int rnewEntNum) { choose_Pr(); roulette(rnewEntNum,group); } /* * 轮盘赌算法 */ private void roulette(int rnewEntNum,String[] group) { //取[0,1]之间的概率片段对应每一个假设成员 double zero_one_Pr[]=new double[groupSize-1]; for(int i=0;i<groupSize-1;i++) { if(i==0)zero_one_Pr[i]=pr[0]; else if(i==groupSize-2)zero_one_Pr[i]=1-pr[groupSize-1]; else { for(int j=0;j<=i;j++) zero_one_Pr[i]+=pr[j]; } System.out.print(zero_one_Pr[i]+" "); } double rand=0; for(int i=0;i<rnewEntNum;i++) { rand=Math.random(); if(rand<zero_one_Pr[0]) group[i]=this.group[0]; else if(rand<zero_one_Pr[1]&&rand>=zero_one_Pr[0]) group[i]=this.group[1]; else if(rand<zero_one_Pr[2]&&rand>=zero_one_Pr[1]) group[i]=this.group[2]; else { group[i]=this.group[3]; } } } /* * 选择群体中每个成员的概率 */ private void choose_Pr() { double sum_pr=0.0;; for(String str:group) { sum_pr+=countFitness(str); } for(int i=0;i<groupSize;i++) { pr[i]=countFitness(group[i])/sum_pr; System.out.println("成员"+group[i]+"被选择的概率(Pr(hi)):"+pr[i]); } } /* * 交叉(总是要在选择之后完成) */ private void intersect(int inter_pair,int inter_start_index) { String[] temp_Group=new String[inter_pair*2]; roulette(inter_pair*2,temp_Group); for(String str:temp_Group) System.out.println("交叉选择的成员:"+str); int len=temp_Group.length; int index1=0,index2=0; List<Integer> list=new ArrayList<Integer>(); int length=len; boolean flag=false; int i=inter_start_index; while(length!=0) { do { index1=(int)(len*Math.random()); flag=isRepeatIndex(index1,list); } while (flag); do { index2=(int)(len*Math.random()); flag=isRepeatIndex(index2,list); } while (flag); String[] temp=new String[2]; temp=intersect_B(temp_Group[index1],temp_Group[index2]); group[i++]=temp[0]; group[i++]=temp[1]; length-=2; } } /* * 在交叉时,判断一个下标(@index)对应的成员是否已经被选择过了 * @temp_index 保存已选择了的成员在临时group中对应的下标 */ private boolean isRepeatIndex(int index,List<Integer> list) { for(int i=0;i<list.size();i++) { if(index==(int)list.get(i)) return true; } list.add(index); return false; } /* * 任意两个成员实现交叉(单点交叉) * @single_point 交叉点位置 */ private String[] intersect_B(String entity1,String entity2) { String[] son_Ent=new String[2]; int single_point=(int)(6*Math.random()); son_Ent[0]=entity1.substring(0,single_point)+entity2.substring(single_point); son_Ent[1]=entity1.substring(single_point)+entity2.substring(0,single_point); return son_Ent; } /* * 变异 *@group 要变异的群体 *@ratio 变异率 *@ */ private void variation(String[] group,double ratio) { int var_Size=(int)(groupSize*ratio); boolean flag=false; List<Integer> list=new ArrayList<Integer>(); int index; while(var_Size>0) { do { index=(int)(groupSize*Math.random()); flag=isRepeatIndex(index, list); } while (flag); int var_site=(int)(6*Math.random()); if(group[index].charAt(var_site)=='0') group[index]=group[index].substring(0,var_site)+'1'+group[index].substring(var_site+1); else if(group[index].charAt(var_site)=='1') group[index]=group[index].substring(0,var_site)+'0'+group[index].substring(var_site+1); var_Size--; } } public static void main(String args[]) { int x[]=new int[2]; String strTest=null; GAFunBVar gaFunBVar=new GAFunBVar(5,6,4,0.5,0.5); strTest=gaFunBVar.coding(gaFunBVar.x1,gaFunBVar.x2); System.out.println(strTest); x=gaFunBVar.enCoding(strTest); gaFunBVar.x1=x[0]; gaFunBVar.x2=x[1]; System.out.println(gaFunBVar.x1+" "+gaFunBVar.x2); gaFunBVar.InitGroup(); System.out.println("初始随机创建一个群体:"); for(int i=0;i<gaFunBVar.groupSize;i++) { System.out.println(gaFunBVar.group[i]); } while(gaFunBVar.noSwapNum<GENERATION) { //1.选择(轮盘赌方法) int rnewEntNum=(int)((1-gaFunBVar.r)*gaFunBVar.groupSize); System.out.println("直接从父代选择成员作为后代的个数:"+rnewEntNum); gaFunBVar.chooseNewEnt(rnewEntNum); //2.交叉 int inter_pair=(int)(gaFunBVar.r*gaFunBVar.groupSize/2); System.out.println("要交叉的对数:"+inter_pair); gaFunBVar.intersect(inter_pair,rnewEntNum); //3.变异 gaFunBVar.variation(gaFunBVar.group, gaFunBVar.m); System.out.println("变异后的群体为:"); for(String str:gaFunBVar.group) System.out.println(str); // gaFunBVar.getMaxFitness(gaFunBVar.group); } System.out.println("最大的适应度为:"+gaFunBVar.maxFitness); System.out.println("达到最大适应度的个体为:"+gaFunBVar.maxFitEntity); } }