||
种群类中的数据成员主要是(2)中Point类型的对象,我们采用一维数组组织这些对象。这种以类A的对象作为类B的成员的方法,在面向对象中称为组合。
为了让父代种群产生的子代种群有存储的空间,一般需要在种群类中设定两个长度相同的数组,分别用于存放父代个体和子代个体,另还需要设定种群演化的交叉率、变异率及种群规模等。
对于Point类,为方便测试个体,可以在Point中增加一个自显示方法简化程序。
public void show() { String strX=""; for(int i=0;i<size;i++) strX=strX+x[i]; System.out.println(strX+","+this.decode()+","+this.getFitness()); }
种群类GA1:
class GA1 { Point[] obj;//当前种群,若干个体构成种群 Point[] nextobj;//下一代种群 private int size;//种群大小 double[] p;//每一个个体的累积概率 double pc=0.8;//交叉率 double pm=0.05;//变异率 double[] norm;//每个个体的适度值 public GA1(int size) { this.size=size; init(); } public void init() { obj=new Point[this.size]; nextobj=new Point[this.size]; p=new double[this.size]; norm=new double[this.size]; for(int i=0;i<this.size;i++) { obj[i]=new Point(); nextobj[i]=new Point(); } } public void calP()//计算轮盘赌累积概率 { double sum=0.0; for(int i=0;i<this.size;i++) { norm[i]=obj[i].getFitness(); } for(int i=0;i<this.size;i++) { sum=sum+norm[i]; } for(int k=0;k<this.size;k++) { norm[k]=(k==0)?(norm[0]):(norm[k-1]+norm[k]); p[k]=norm[k]/sum;//计算累积概率 } } //轮盘赌选择 public int select() { int pos=0; double pa=Math.random(); for(int i=0;i<this.size;i++) { if(pa<p[i]) { pos=i; break; } } return pos; } //两点交叉 public void crossTwo(Point a,Point b,Point ab,Point ba) { int pos1; int pos2; int temp; pos1=(int)(Math.random()*Point.size); pos2=(int)(Math.random()*Point.size); if(pos1>pos2) { temp=pos1;pos1=pos2;pos2=temp; } System.arraycopy(a.x,0,ab.x,0,pos1); System.arraycopy(b.x,0,ba.x,0,pos1); System.arraycopy(b.x,pos1,ab.x,pos1,pos2-pos1); System.arraycopy(a.x,pos1,ba.x,pos1,pos2-pos1); System.arraycopy(a.x,pos2,ab.x,pos2,Point.size-pos2); System.arraycopy(b.x,pos2,ba.x,pos2,Point.size-pos2); } //变异 public void mut(Point a) { int pos=(int)(Math.random()*Point.size); a.x[pos]=(a.x[pos]+1)%2; } //查找最佳个体的位置 public int bestPos() { int pos=0; Point best=new Point(); System.arraycopy(obj[0].x,0,best.x,0,Point.size); for(int i=1;i<this.size;i++) { if(best.getFitness()<obj[i].getFitness()) { System.arraycopy(obj[i].x,0,best.x,0,Point.size); pos=i; } } return pos; } //查找最差个体的位置 public int badPos() { int pos=0; Point bad=new Point(); System.arraycopy(obj[0].x,0,bad.x,0,Point.size); for(int i=1;i<this.size;i++) { if(bad.getFitness()>nextobj[i].getFitness()) { System.arraycopy(nextobj[i].x,0,bad.x,0,Point.size); pos=i; } } return pos; } //选择-交叉-变异算子的集成 public void doAll() { int bestposObj; int badposnextObj; Point best=new Point(); int ipos,jpos; //记录最好的父代个体位置 bestposObj=this.bestPos(); this.calP(); //依据概率交叉生成第二代 for(int i=0;i<this.size/2;i++) { ipos=this.select(); jpos=this.select(); if(Math.random()<pc) this.crossTwo(obj[ipos],obj[jpos],nextobj[2*i],nextobj[2*i+1]); else { System.arraycopy(obj[ipos].x,0,nextobj[2*i].x,0,Point.size); System.arraycopy(obj[jpos].x,0,nextobj[2*i+1].x,0,Point.size); } } //依据概率变异 for(int i=0;i<this.size;i++) { if(Math.random()<pm) this.mut(nextobj[i]); } //父代最优替换子代最差 badposnextObj=this.badPos(); if(obj[bestposObj].getFitness()>nextobj[badposnextObj].getFitness()) System.arraycopy(obj[bestposObj].x,0,nextobj[badposnextObj].x,0,Point.size); //产生成熟的新一代 for(int i=0;i<this.size;i++) System.arraycopy(nextobj[i].x,0,obj[i].x,0,Point.size); } }
然后创建一个主类测试即可。
public class TestGA1 { public static void main(String[] arg) { int size=30; Point.set(22,2.0,-1.0); GA1 s=new GA1(size); Point best=new Point(); int n=0; int gen=0;//记录最好的个体出现的代数 while(n<500) { s.doAll(); if(best.getFitness()<s.obj[s.bestPos()].getFitness()) {best=s.obj[s.bestPos()]; gen++; } n++; } int bestpos=s.bestPos(); s.obj[bestpos].show(); System.out.println(gen); } }
至此,一个完整的遗传算法完成。
Archiver|手机版|科学网 ( 京ICP备07017567号-12 )
GMT+8, 2024-12-22 14:29
Powered by ScienceNet.cn
Copyright © 2007- 中国科学报社