您的位置:首页 > 其它

一个简单问题的遗传算法的实现

2010-05-23 14:54 405 查看
刚开始研究遗传算法,所以先尝试用该算法实现解决一个简单的问题问题如下:

求函数

f(x)=x^2

在区间

[0,31]

内的最大值,其中

x

取整数

利用遗传算法解决的

思路如下:

1.

编码策略

用五位二进制表示

x



0~31



32

个数

2.

初始种群

初始种群为随机的

4

个个体

3.

适应函数

将二进制转换为十进制,并取其平方即得到适应度

4.

选择算子

适应性大的个体被选中的概率也大

5.

交叉算子与变异算子

交叉概率为

1

,变异概率为

0.01

交叉点为随机产生的一个范围为

1-5

的数,假定产生一个随机数位

3

,则

10000



11111

交叉后为

10111



11000

以下是该算法的java代码实现,代码写的时间比较短,没怎么优化及注释,不过可以看到结果了。代码只输出了遗传算法中每一代中的种群个体染色体情况。从代码的输出结果可以看出,算法找到了最优解11111,但是由于变异的存在,又会跳到其他解,不过运行几秒之后停下来后你会发现他的解是接近最优的。

import java.util.Random;
/**
* 一个遗传算法的简单例子:
* 求函数f(x)=x^2在区间[0,31]内的最大值,其中x取整数
*/
/**
* 思路:
* 1.编码策略
* 		用五位二进制表示x的0~31共32个数
* 2.初始种群
* 		初始种群为随机的4个个体
* 3.适应函数
* 		将二进制转换为十进制,并取其平方即得到适应度
* 4.选择算子
* 		适应性大的个体被选中的概率也大
* 5.交叉算子与变异算子
* 		交叉概率为1,变异概率为0.01
* 		交叉点为随机产生的一个范围为1-5的数,假定产生一个随机数位3,则10000与11111交叉后为10111,11000
*/
/**
*	@author 	lgjfly
*	Class:	GATest.java
*	Date:	2010-5-23
*	@see http://blog.csdn.net/lgjfly */
public class GATest {
public static void main(String[] args) {
// TODO Auto-generated method stub
GATest test = new GATest();
test.GA();
}
//遗传算法核心
public int GA() {
int[][] syngen = new int [4][5];//种群,共4个个体,每个个体编码为5位
int[] f=new int[4];//对应于每一个个体的适应度
int fsum=0;//适应度总和
int i,j;
Random random = new Random();
//随机产生初始种群
for(i=0;i<4;i++) {
for(j=0;j<5;j++) {
syngen[i][j]=Math.abs(random.nextInt())%2;
}
}

int[] p= new int [4];//对应的个体能够存活的概率*100
int[] survived= new int [4];//筛选之后对应的个体生存下来的个数
int m;//临时数
int generation=0;
while(fsum<100000) {
generation++;
System.out.print("the "+generation+" generation : ");
for(i=0;i<4;i++) {
for(j=0;j<5;j++) {
System.out.print(syngen[i][j]);
}
System.out.print(" ");
}
System.out.print("/n ");
fsum=0;
//计算当前代的种群适应度
for(i=0;i<4;i++) {
f[i]=Evaluate(syngen[i]);
fsum+=f[i];
}
//计算当前代的每一个个体存活的概率,并将survived清零
for(i=0;i<4;i++) {
p[i]=(100*f[i])/fsum;
survived[i]=0;
}
//得到生存下来的个体的下标
for(i=0;i<4;i++) {
m=Math.abs(random.nextInt())%100;
if(m<p[0])
survived[0]++;
else if(m<p[0]+p[1])
survived[1]++;
else if(m<p[0]+p[1]+p[2])
survived[2]++;
else
survived[3]++;
}
//由下标得到新种群
for(i=0;i<4;i++) {
if(survived[i]>0)
continue;
//从前面找第一个大于一的
j=0;
while(survived[j]<=1) j++;
//将j复制给i
System.arraycopy(syngen[j], 0, syngen[i], 0, syngen[i].length);
survived[j]--;
}
//交换
m=Math.abs(random.nextInt())%3+1;
Exchange(syngen[0],syngen[m]);
if(m==1)
Exchange(syngen[2],syngen[3]);
else if(m==2)
Exchange(syngen[1],syngen[3]);
else
Exchange(syngen[1],syngen[2]);

//变异
if(generation%8==0) {
i=Math.abs(random.nextInt())%4;
j=Math.abs(random.nextInt())%5;
syngen[i][j]=(syngen[i][j]+1)%2;
}
}
return 0;
}

//交叉算子,交换数组a,b后的随机位数
public int Exchange(int[] a,int[] b) {
Random random = new Random();
int expoint=Math.abs(random.nextInt())%5;//交叉点位置,为一个1-5之间的数
int temp;
for(int i=expoint;i>0;i--) {
//交换a[i],b[i]
temp=a[i];
a[i]=b[i];
b[i]=temp;
}
return 0;
}
//适应函数
public int Evaluate(int[] a) {
int value=0;
//将a转换为十进制
for(int i=0;i<5;i++) {
value=value*2+a[i];
}
value=value*value;
return value;
}
}


本文参考了《人工智能导论》(鲍军鹏,张选平等著,机械工业出版社,第207-209页)

本文为lgjfly原著,转载时请注明出处:http://blog.csdn.net/lgjfly
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐