计算智能课的遗传算法上完了,老师布置了一个简单的应用,用java实现了下。
首先是题目要求:
Use genetic algorithm to find a near-maximal value in
f==xsin(10*pi*x)+2
[-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 final int POP_SIZE=30;//种群数目
public static final int M=22; //编码位数
public static String[]pop=new String[POP_SIZE];//种群编码
public static double[]result=new double[POP_SIZE];//种群代表的结果
public static final int LENGTH=22;//编码长度,因为要精确到小数点后六位,所以编为22位长,有一公式可参考
public static final int MJ2=4194304;//2^22
public static double[]fitness=new double[POP_SIZE];//存放种群适应度
public static final double PC=0.95;//交叉率
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之和
public static Random random=new Random();//用于产生随机数的工具
public static Best best=new Best();//记录最佳答案的对象
/*
* 构造函数,初始化种群
*/
public GA(double d[])
{
for (int i = 0; i < d.length; i++) {
result[i]=d[i];
}
}
/*
* 编码方法,将解值表示为二进制字节码形式
*/
public void encoding()
{
for (int i = 0; i < result.length; i++) {
double d1=((result[i]-A)/(B-A))*(MJ2-1);
pop[i]=Integer.toBinaryString((int)d1);
}
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];
}
}
}
for (int i = 0; i < pop.length; i++) {
//System.out.println(pop[i]+" "+pop[i].length());
}
}
/*
* 解码方法,讲二进制字节码还原为解
*/
public void decoding()
{
for (int i = 0; i < pop.length; i++) {
int k=Integer.parseInt(pop[i], 2);
result[i]=A+k*(B-A)/(MJ2-1);
}
for (int i = 0; i < result.length; i++) {
// System.out.println(result[i]);
}
}
/*
* 适应度函数
*/
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 crossover()
{
for (int i = 0; i < POP_SIZE/2; i++) {
double d=random.nextDouble();
if(d<PC)
{
int k1=random.nextInt(POP_SIZE);
int k2=random.nextInt(POP_SIZE);
do {
k1=(int)random.nextInt(POP_SIZE);
k2=(int)random.nextInt(POP_SIZE);
} while (k1==k2);
int position=random.nextInt(LENGTH);
//System.out.println("crossover position="+position+" "+k1+ " "+k2);
String s11=null,s12=null,s21=null,s22=null;
//System.out.println(pop[k1]+" "+pop[k1].length());
s11=pop[k1].substring(0, position);
s12=pop[k1].substring(position,LENGTH);
//System.out.println(pop[k2]+" "+pop[k2].length());
s21=pop[k2].substring(0, position);
s22=pop[k2].substring(position,LENGTH);
pop[k1]=s11+s22;
pop[k2]=s21+s12;
}
}
}
/*
* 变异操作
*/
public void mutation()
{
for (int i = 0; i < pop.length; i++) {
for (int j = 0; j < LENGTH; j++) {
double k=random.nextDouble();
if(PM>k)
{
mutation(i,j);
}
}
}
}
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 roulettewheel()
{
decoding();
fitness();
double sum=0;
for (int i = 0; i <POP_SIZE; i++) {
sum=fitness[i]+sum;
}
for (int i = 0; i < POP_SIZE; i++) {
p[i]=fitness[i]/sum;
}
for (int i = 0; i < POP_SIZE; i++) {
for (int j = 0; j < i+1; j++) {
q[i]=p[j];
}
}
double []ran=new double[POP_SIZE];
String[] tempPop=new String[POP_SIZE];
for (int i = 0; i < ran.length; i++) {
ran[i]=random.nextDouble();
}
for (int i = 0; i < ran.length; i++) {
int k = 0;
for (int j = 0; j < q.length; j++) {
if(ran[i]<q[j])
{
k=j;
break;
}
else continue;
}
tempPop[i]=pop[k];
}
for (int i = 0; i < tempPop.length; i++) {
pop[i]=tempPop[i];
}
}
/*
* 一次进化
*/
public void evolution()
{
encoding();
crossover();
mutation();
decoding();
fitness();
roulettewheel();
findResult();
}
/*
*整个进化过程,n 表示进化多少代
*/
public void dispose(int n)
{
for (int i = 0; i < n; i++) {
evolution();
}
}
/*
* 取得结果
*/
public double findResult()
{
if(best==null)
best=new Best();
double max=best.fitness;
for (int i = 0; i < fitness.length; i++) {
if(fitness[i]>max)
{
best.fitness=fitness[i];
best.x=result[i];
best.str=pop[i];
//System.out.println(best.fitness);
}
}
return max;
}
/*
* 取得x值
*
*/
public double findx()
{
fitness();
double max=0;
int index=0;
for (int i = 0; i < fitness.length; i++) {
System.out.println(result[i]);
if(fitness[i]>max)
{
max=fitness[i];
index=i;
}
}
return result[index];
}
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);
System.out.println("+++++++++++++++++++++++++++结果为:");
System.out.println("x="+best.x);
System.out.println("f="+best.fitness);
}
}
class Best { // 存储最佳的
public int generations;
public String str;
public double fitness;
public double x;
}