君子不器分享 http://blog.sciencenet.cn/u/foreverph

博文

演化计算:基于面向对象设计的认知(3)

已有 1972 次阅读 2021-6-20 10:29 |个人分类:算法|系统分类:科研笔记

种群类中的数据成员主要是(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);
}
}

至此,一个完整的遗传算法完成。



https://blog.sciencenet.cn/blog-260510-1291929.html

上一篇:演化计算:基于面向对象设计的认知(2)
下一篇:演化计算:基于面向对象设计的认知(4)
收藏 IP: 117.187.32.*| 热度|

0

该博文允许注册用户评论 请点击登录 评论 (0 个评论)

数据加载中...

Archiver|手机版|科学网 ( 京ICP备07017567号-12 )

GMT+8, 2024-12-22 03:00

Powered by ScienceNet.cn

Copyright © 2007- 中国科学报社

返回顶部