package wh.algorithm;
public class SGA {
private static Bion best = null; // 最佳个体
private static String[] ipop = new String[10];// 染色体
private static int gernation = 0;// 染色体代号
private static final int GENE = 22;// 基因数
private static int INTERVALVALUE=255;
private static final int EVOLUTION_NUMBER=100000;//进化次数
public static void main(String[] args) {
System.out.printf("利用标准遗传算法求解函数f(x)=(x-22)*(x-22)的最小值,X的区间[-%d,%d].\n",INTERVALVALUE,INTERVALVALUE);
SGA sga = new SGA();
String bestReuslt = sga.process();
System.out.println(bestReuslt);
}
public SGA() {
ipop = initPops();
}
/**
* 初始化一条染色体(用二进制字符串表示)
*
* @return 一条染色体
*/
private String initPop() {
String res = "";
for (int i = 0; i < GENE; i++) {
if (Math.random() > 0.5) {
res += "0";
} else {
res += "1";
}
}
return res;
}
/**
* 初始化一组染色体
*
* @return 染色体组
*/
private String[] initPops() {
String[] ipop = new String[10];
System.out.println("初始化个体...");
for (int i = 0; i < 10; i++) {
ipop[i] = initPop();
// System.out.printf("ipop[%d]:%s %s\n", i, ipop[i],
// Integer.parseInt(ipop[i], 2));
}
return ipop;
}
/**
* 将染色体转换成x的值
*
* @param str
* 染色体
* @return 染色体的适应值
*/
private double calculatefitnessvalue(String str) {
double x = binary2Double(str);
double fitness = -(x - 22) * (x - 22);
// System.out.printf("X=%f,f(x)=%f\n",x,fitness);
return fitness;
}
/**
* 计算群体上每个个体的适应度值; 按由个体适应度值所决定的某个规则选择将进入下一代的个体;
*/
private void select() {
double evals[] = new double[10]; // 所有染色体适应值
double p[] = new double[10]; // 各染色体选择概率
double q[] = new double[10]; // 累计概率
double F = 0; // 累计适应值总和
for (int i = 0; i < 10; i++) {
evals[i] = calculatefitnessvalue(ipop[i]);
if (best == null) {
best = new Bion();
best.fitness = evals[i];
best.generations = 0;
best.chromosome = ipop[i];
} else {
if (evals[i] > best.fitness) // 最好的记录下来
{
best.fitness = evals[i];
best.generations = gernation;
best.chromosome = ipop[i];
}
}
F = F + evals[i]; // 所有染色体适应值总和
}
for (int i = 0; i < 10; i++) {
p[i] = evals[i] / F;
if (i == 0)
q[i] = p[i];
else {
q[i] = q[i - 1] + p[i];
}
}
for (int i = 0; i < 10; i++) {
double r = Math.random();
if (r <= q[0]) {
ipop[i] = ipop[0];
} else {
for (int j = 1; j < 10; j++) {
if (r < q[j]) {
ipop[i] = ipop[j];
break;
}
}
}
}
}
/**
* 交叉操作 交叉率为25%,平均为25%的染色体进行交叉
*/
private void cross() {
String temp1, temp2;
for (int i = 0; i < 10; i++) {
if (Math.random() < 0.25) {
double r = Math.random();
int pos = (int) (Math.round(r * 1000)) % GENE;
if (pos == 0) {
pos = 1;
}
temp1 = ipop[i].substring(0, pos)
+ ipop[(i + 1) % 10].substring(pos);
temp2 = ipop[(i + 1) % 10].substring(0, pos)
+ ipop[i].substring(pos);
ipop[i] = temp1;
ipop[(i + 1) / 10] = temp2;
}
}
}
/**
* 基因突变操作 1%基因变异m*pop_size 共180个基因,为了使每个基因都有相同机会发生变异, 需要产生[1--180]上均匀分布的
*/
private void mutation() {
for (int i = 0; i < 4; i++) {
int num = (int) (Math.random() * GENE * 10 + 1);
int chromosomeNum = (int) (num / GENE) + 1; // 染色体号
int mutationNum = num - (chromosomeNum - 1) * GENE; // 基因号
if (mutationNum == 0)
mutationNum = 1;
chromosomeNum = chromosomeNum - 1;
if (chromosomeNum >= 10)
chromosomeNum = 9;
// System.out.println("变异前" + ipop[chromosomeNum]);
String temp;
if (ipop[chromosomeNum].charAt(mutationNum - 1) == '0') {
if (mutationNum == 1) {
temp = "1" + ipop[chromosomeNum].substring(mutationNum);
} else {
if (mutationNum != GENE) {
temp = ipop[chromosomeNum].substring(0, mutationNum - 1)+ "1"+ ipop[chromosomeNum].substring(mutationNum);
} else {
temp = ipop[chromosomeNum].substring(0, mutationNum - 1) + "1";
}
}
} else {
if (mutationNum == 1) {
temp = "0" + ipop[chromosomeNum].substring(mutationNum);
} else {
if (mutationNum != GENE) {
temp = ipop[chromosomeNum].substring(0, mutationNum -
1) + "0" + ipop[chromosomeNum].substring(mutationNum);
} else {
temp = ipop[chromosomeNum].substring(0, mutationNum - 1) + "1";
}
}
}
ipop[chromosomeNum] = temp;
// System.out.println("变异后" + ipop[chromosomeNum]);
}
}
public double binary2Double(String binary) {
return -INTERVALVALUE + Integer.parseInt(binary, 2) * (INTERVALVALUE - (-INTERVALVALUE))
/ (Math.pow(2, GENE) - 1);
}
/**
* 执行遗传算法
*/
public String process() {
System.out.printf("开始进化,进化次数%d\n",EVOLUTION_NUMBER );
System.out.printf("进化中............\n");
long startTime = System.nanoTime();
String str = "";
for (int i = 0; i < EVOLUTION_NUMBER; i++) {
this.select();
this.cross();
this.mutation();
gernation = i;
}
long endTime = System.nanoTime();
long costtime = endTime - startTime;
System.out.printf("进化耗时:%d(ms)\n", costtime / 1000000);
str = "最小值F(X)=" + best.fitness + " ,X="
+ binary2Double(best.chromosome) + ",第" + best.generations
+ "个染色体";
return str;
}
}
class Bion {
public int generations; // 最佳适应值代号
public String chromosome; // 最佳染色体
public double fitness; // 最佳适应值
}
测试结果:
利用标准遗传算法求解函数f(x)=(x-22)*(x-22)的最小值,X的区间[-255,255].
初始化个体...
开始进化,进化次数100000
进化中............
进化耗时:4003(ms)
最小值F(X)=-4.382968527749637E-6 ,X=21.997906445957767,第66072个染色体