一个简单的遗传算法的应用实例(java代码)

求下述二元函数的最大值:


下参考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);
	}
}

  程序整体上有点乱,第一次写,多多包含 微笑

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值