简单遗传算法的小例子

我对别人写的遗传算法java代码进行了一点修改。(大家可以在原文的文档中找到代码的出处)。它也实现了简单遗传算法的基本功能。这份代码的注释比较多。我认为这份代码条理较为清晰。请多多指教。这份代码主要取材自这两篇文章:主体来自于:http://www.cnblogs.com/macula7/archive/2009/04/04/1960673.html轮盘赌算法来自于:http://www.cnblogs.com/heaad/archive/2010/12/23/1914725.html这份代码的程序流程图如下:(这是简单遗传算法的框图)


/*A given function is as follows:
Use genetic algorithm to find a near-maximal value in f=xsin(10*pi*x)+2 
x的定义域为[-1,2]. 
In addition, the required precision is six places after the decimal point.
 */
import java.util.Random;

public class GA {
	public static final double A = -1;                 // 定义域下界
	public static final double B = 2;                  // 定义域上界
	public static Best best;                           // 记录最佳答案的对象
	public static final int POP_SIZE = 30;             // 种群大小(本题的种群由30个个体(即x)组成)
	public static String[] pop = new String[POP_SIZE];    // String型数组,存放种群中每个个体(即x)的编码
	public static double[] result = new double[POP_SIZE]; // double型数组,经过进化后的种群中的每个个体(即x)
	public static double[] fitness = new double[POP_SIZE];//double型,存放种群中每个个体(即x)的适应值
	public static final int LENGTH = 22; // x的编码长度,因为要精确到小数点后六位,所以十进制的整数部分(1位)与小数部分(6位)共有7位。这需要用22位的二进制数表示。
	public static final int conversionFactor = 4194303;//转换因子,22位二进制数所能表示最大的十进制数为2^22-1
	public static Random random = new Random();     // 用于产生随机数的工具
	public static final double PM = 0.05;           // 变异率
	public static double[] p = new double[POP_SIZE];// 轮盘赌方法个体适应度概率
	public static double[] q = new double[POP_SIZE];// q[i]是前n项p之和
	int k1,k2;	//被选出来杂交的两个个体	


	/*
	 * 构造方法,初始化种群
	 */
	public GA(double d[]) {
		for (int i = 0; i < d.length; i++) {
			result[i] = d[i];
		}
	}
	
	/*
	 * 适应度函数,在本例中,使函数值f(x)越大,x的适应值越高。
	 */
	public void fitness() {
		for (int i = 0; i < result.length; i++) {
			fitness[i] = result[i] * (Math.sin(10 * Math.PI * result[i])) + 2;
			// System.out.println(fitness[i]);
		}
	}
	
	/*
	 * 编码方法,将解值表示为二进制字节码形式
	 */
	public void encoding()
	{
		for (int i = 0; i < result.length; i++) {
			//放大result[i]以利于编码。
			//d1的值:(|result[i]与A点的距离|/(定义域的长度))*转换因子
			double d1 = ((result[i] - A) / (B - A)) * (conversionFactor);
			//将d1强制类型转换成int型,并将其转换成二进制的字符串,并放入pop数组中。
			pop[i] = Integer.toBinaryString((int) d1);
		}
		//依次检验pop数组的每一项,如果它的长度!=22,则在前面补“0”使其达到22位
		for (int i = 0; i < pop.length; i++) {
			if (pop[i].length() < LENGTH) {
				int k = LENGTH - pop[i].length();
				for (int j = 0; j < k; j++) {
					pop[i] = "0" + pop[i];
				}
			}
		}
	}
	
	/*
	 * 选择操作,依据轮盘赌算法从种群中选出两个个体进行杂交。
	 */
	public void selection()
	{
		int k1;
		int k2;
		do {
			k1 = roulettewheel();
			k2 = roulettewheel();
		} while (k1 != k2);
	}
	
	/*
	 * 轮盘赌算法,适应值大的个体被选中的机率更大些。
	 */
	int roulettewheel()
	{
	    double m = 0;
	    double r =random.nextDouble(); //r为0至1的随机数
	    int i = 0;
	    for(i=0;i<=LENGTH; i++)
	    {
	            /* 产生的随机数在m~m+P[i]间则认为选中了i
	             *  因此i被选中的概率是P[i]
	             */
	             m = m + fitness[i];
	             if(r<=m)
	            	 break;
	    }
	    return i;
	}
	
	/*
	 * 解码方法,将二进制字节码还原
	 */
	public void decoding() {
		for (int i = 0; i < pop.length; i++) {
			int k = Integer.parseInt(pop[i], 2);
			result[i] = A + k * (B - A) / (conversionFactor);
		}
	}

	/*
	 * 交叉操作
	 */
	public void crossover() {
		//随机产生是染色体发生交叉操作的位置
		int position = random.nextInt(LENGTH);
		//s1字符串被切成s11和s12,s2字符串被切成s21,s22
		String s11 = null, s12 = null, s21 = null, s22 = null;
		s11 = pop[k1].substring(0, position);
		s12 = pop[k1].substring(position, LENGTH);
		s21 = pop[k2].substring(0, position);
		s22 = pop[k2].substring(position, LENGTH);
		//重新拼接字符串,并放入种群
		pop[k1] = s11 + s22;
		pop[k2] = s21 + s12;
	}

	/*
	 * 变异操作,变异在染色体上的每个基因都可能发生
	 */
	public void mutation() {
		//第i个个体(即染色体)
		for (int i = 0; i < pop.length; i++) {
			//第i个个体第j号基因
			for (int j = 0; j < LENGTH; j++) {
				double k = random.nextDouble();
				//如果产生的随机数k小于变异率,则进行变异操作。
				if (PM > k) {
					mutation(i, j);
				}
			}
		}
	}
	//如果基因的位置是“1”则换为“0”。如果基因的位置是“0”则换为“1”。
	public void mutation(int i, int j) {
		String s = pop[i];
		StringBuffer sb = new StringBuffer(s);
		if (sb.charAt(j) == '0')
			sb.setCharAt(j, '1');
		else
			sb.setCharAt(j, '0');
		pop[i] = sb.toString();

	}
	
	/*
	 * 一次进化
	 */
	public void evolution() {
		fitness();          //计算适应度
		encoding();         //编码
		selection();        //选择
		crossover();        //交叉
		mutation();         //变异
		decoding();         //解码
	}

	/*
	 * 整个进化过程,n 表示进化多少代
	 */
	public void dispose(int n) {
		for (int i = 0; i < n; i++) {
			evolution();
		}
	}

	/*
	 * 取得结果
	 */
	public double findBestOne() {
		if (best == null)
			best = new Best();
		double max = 0;
		for (int i=0;i<fitness.length; i++) {
			if (fitness[i] > max) {
				max = fitness[i];
				best.fitness = max;
				best.x = result[i];
				best.str = pop[i];
			}
		}
		return max;
	}
	
	/*
	 * 保存最佳个体的对象
	 */
	class Best { 
		public int generations;
		public String str;
		public double fitness;
		public double x;
	}

	public static void main(String[] args) {
		// d为初始数据
		double d[] = { -0.953181, -0.851234, -0.749723, -0.645386, -0.551234,
				-0.451644, -0.351534, -0.239566, -0.151234, 0.145445, 0.245445,
				0.285174, 0.345445, 0.445445, 0.542445, 0.645445, 0.786445,
				0.845445, 0.923238, 1.245445, 1.383453, 1.454245, 1.584566,
				1.644345, 1.741545, 1.845445, 1.981254, -0.012853, 0.083413,
				1.801231 };
		// 初始化初始种群及其他数据
		GA ga = new GA(d);
		System.out.println("种群进化中....");
		// 进化,这里进化10000次
		ga.dispose(10000);
		ga.findBestOne();       //取得结果
		System.out.println("+++++++++++++++++++++++++++结果为:");
		System.out.println("x=" + best.x);
		System.out.println("f=" + best.fitness);
		//for(double i :result)
		//{
		//	System.out.println(i);
		//}
	}
}

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值