貌似遗传算法看起来挺神秘的,但要真正初步的了解一下它的大概思想还是挺简单的。我只想用最通俗的话和最简单的编程来讲讲遗传算法。
先来求解一个最简单的问题,求解f(x)=x*2的最大值 , x属于[0,31];即求解x的平方在[0,31]的最大值.现在我们用遗传算法来求解这个题目。
先解释一下生物界的一些基础知识:
1:染色体和基因,染色体可以理解为一段字符串编码,唯一的表示个体的特征的,如1001,就表示一个染色体,1,0,0,1这样的就是基因
2:选择,就是比较合适环境的个体生存下来,不合适环境的个体会被淘汰,
3:交叉,也就是繁殖,就是一个个体遗传父母的基因,有好基因,也有不好的基因,如下面
1001 1000
//遗传算法构造函数 public GA() { String s; for(int i=0;i<4;i++){ s = Integer.toBinaryString(r.nextInt(32));//产生随机[0,31]的随机数 //,并且转换为二进制表示 while(s.length()<5){ //空位补0,补齐5位 s = "0"+s; } chromosome[i] = s;//这是初始化种群大小,即一开始有多少个体,我这里选择4个String[] array = new String[4]; } gcount = 0; //全局变量,表示当前第几代,先不用管 // print("初始化:"); }
//选择 void select(){ int min = 0; int max = 0; for(int i=0;i<4;i++){ //从4个个体中把最大适应度个体代替最低适应度个体,fitArray数组表示4个染色体的适应度 fitArray[i] = fit(chromosome[i]);//fit函数计算个体(也就是染色体)的适应度 if(fitArray[i]<fitArray[min]){ min = i; } if(fitArray[i]>fitArray[max]){ max = i; } } if(fitArray[max]>bestFit){ //bestFit和bestChromosome是全局最优解,即我们最终的结果会在这里出现, bestFit = fitArray[max]; //bestFit代表至今最好的适应度 bestChromosome = chromosome[max];//bestChromosome代表至今最好的染色体 } chromosome[min] = chromosome[max]; print("选择后:"); } //求染色体x的适应度函数 double fit(String x){ int i = Integer.parseInt(x, 2); return (double)i*i; }
3:交叉
//交叉 void cross(){ if(Math.random()<0.25){//交叉的概率,为了好讲解,这个可以先不管,后面还会说到,先假设一定会交叉 return; } char[] cr[] = new char[4][5]; //随机产生4个染色体中哪两个需要交叉 int a = r.nextInt(4); int b = r.nextInt(4); for(int i=0;i<4;i++){ cr[i] = chromosome[i].toCharArray(); } //随机产生交叉的位置j和l,因为染色体为5位,所以值要小于5 int j = r.nextInt(5); int l = r.nextInt(5); if(l<j){ //在a和b染色体中l到j位中产生交叉操作 for(int k=l;k<j;k++){ char u = cr[a][k]; cr[a][k] = cr[b][k]; cr[b][k] = u; } }else{ //在a和b染色体中j到l位中产生交叉操作 for(int k=j;k<l;k++){ char u = cr[a][k]; cr[a][k] = cr[b][k]; cr[b][k] = u; } } //交叉后重新赋值给染色体 for(int i=0;i<4;i++){ chromosome[i] = new String(cr[i]); } print("交叉后:"); }
4:变异
//变异 void variation(){ if(Math.random()>0.1)return;//变异的概率是0.1 int i = r.nextInt(4);//哪一个个体变异 int j = r.nextInt(5);//个体的哪一位变异 char[] c = chromosome[i].toCharArray(); if(c[j]=='0'){ c[j] = '1'; }else{ c[j] = '0'; } chromosome[i] = new String(c); print("变异后:"); }
5:迭代求最终结果
public static void main(String[] args) { GA ga = new GA(); for(int i=0;i<1000;i++){ ga.select(); ga.cross(); ga.variation(); ga.gcount++; System.out.println("第几代.."+ga.gcount); } System.out.println("最好的适应度:"+bestFit+" 最好的值;"+bestChromosome); }
初始化: 01100 11000 01010 00110 选择后: 01100 11000 01010 11000 交叉后: 01100 11000 01010 11000 第几代..1 选择后: 01100 11000 11000 11000 交叉后: 01000 11000 11000 11100 第几代..2 选择后: 11100 11000 11000 11100 交叉后: 11000 11000 11100 11100 变异后: 11000 11000 10100 11100 ................................ 选择后: 11111 11111 11111 11111 交叉后: 11111 11111 11111 11111 第几代..998 选择后: 11111 11111 11111 11111 第几代..999 选择后: 11111 11111 11111 11111 交叉后: 11111 11111 11111 11111 第几代..1000 最好的适应度:961.0 最好的值;11111