1.简述
关于遗传算法-百度百科的介绍,直接百度百科吧
2.数学问题
这个比较简单的数学公式
当a,b,c,d四个变量取值为 [-2,2] 时,Y的最小值是多少?a、b、c、d、分别是多少?
对与这种公式,凭借小学三年级的功底,得出:最小值 Y=-20,{a=2,b=-2,c=3,d=-2}
既然已经知道了最优解,接下来让我们写一下程序看看求出来到最优解是否与我们算出来的一致
3.java实现
package de;
public class MYDE {
public static void main(String[] args) {
int NP=10;//种群规模
int SIZE=4; //需要有a、b、c、d,4个参数,所以是4
int maxGen=200;//迭代次数
double CR=0.2;//交叉概率
double MU=0.2;//变异概率
double MAX=-2;//abcd变量的上限
double MIN=2;//abcd变量的下限
double [][] init_population=new double [NP][SIZE];//初始化种群
double [][] select_population=new double [NP][SIZE];//选择后的优质种群
double [][] cr_population=new double [NP][SIZE];//交叉后种群
double [][] mu_population=new double [NP][SIZE];//变异后种群
double [] best_individual=new double [SIZE]; //精英个体,及全局最优解
double best_Y=Integer.MAX_VALUE; //精英适应度
double [] Y=new double[NP]; //对应种群中每个个体的适应度
double [] addSumP=new double [NP];//每个个体被选中的概率累加和
//1.初始化种群
for(int i=0;i<NP;i++) {
for(int j=0;j<SIZE;j++) {
init_population[i][j]=MIN+Math.random()*(MAX-MIN);//随机生成解
}
}
/*
* 种群初始化以后,就有了NP个解
*/
//迭代
for(int G=0;G<maxGen;G++) {
//2.选择优质个体,根据轮盘赌的形式挑选个体
double sumY=0;
for(int i=0;i<NP;i++) {//计算每个个体的适应度及全部适应度和
Y[i]=function(init_population[i]);
sumY+=Y[i];
}
double addSum=0;
for(int i=0;i<NP;i++) {//记录每个个体别选中的累加和
addSum+=Y[i]/sumY; //当前个体概率
addSumP[i]=addSum; //累加和
// System.out.println("累加和"+addSum);
}
//根据累加和概率,判断轮盘指针是向那个个体
for(int i=0;i<NP;i++) {
double r=Math.random();
int index=0;
for(int k=0;k<NP;k++) {
if(r<addSumP[k]) {
index=k;break;//选择了一个个体下标是index
}
}
select_population[i]=init_population[index];
}
//3.交叉
for(int i=0;i<NP;i++){
double cr=Math.random();
if(cr<CR) {//判断是否交叉
//与哪个个体交叉,随机生成一个个体
int indiv=(int)Math.random()*NP;
//从那个位置交叉,随机生成一个位置
int index=(int)Math.random()*SIZE;
for(int j=0;j<SIZE;j++) {
if(j>=index){//发生交叉的片段
cr_population[i][j]=select_population[indiv][j];
}else { //不发生交叉的片段
cr_population[i][j]=select_population[i][j];
}
}
}else {
for(int j=0;j<SIZE;j++) {
cr_population[i][j]=select_population[i][j];
}
}
}
//4.变异
for(int i=0;i<NP;i++){
for(int j=0;j<SIZE;j++) {
double mu=Math.random();
if(mu<MU) { //判断是否变异
mu_population[i][j]=MIN+Math.random()*(MAX-MIN);
}else {
mu_population[i][j]=cr_population[i][j];
}
}
}
//输出当前迭代中最优解
for(int i=0;i<NP;i++){
if(best_Y>function(mu_population[i])) {
for(int j=0;j<SIZE;j++){
best_individual[j]= mu_population[i][j];
}
best_Y=function(mu_population[i]);
}
}
System.out.println("第"+G+"代,最小适应度为:"+best_Y);
//5.保留优质个体
for(int i=0;i<NP;i++){
if(function(init_population[i])>function(mu_population[i])) {
for(int j=0;j<SIZE;j++) {
init_population[i][j]=mu_population[i][j];
}
}
}
}//迭代结束
System.out.println("最优解空间为:");
for(int j=0;j<SIZE;j++){
System.out.print(" "+best_individual[j]);
}
}
//计算适应度,及函数式的解
public static double function(double [] individual) {
//传入个体计算Y值
double result=-individual[0]+2*individual[1]-3*individual[2]+4*individual[3];
return result;
}
}
//微信搜索公众号:六行代码
//可以同作者讨论答疑
4.结果展示
第0代,最小适应度为:-0.29731169154051607
第1代,最小适应度为:-7.920632702752841
第2代,最小适应度为:-11.939788517177227
第3代,最小适应度为:-11.939788517177227
第4代,最小适应度为:-11.939788517177227
第5代,最小适应度为:-12.812922259468976
第6代,最小适应度为:-12.812922259468976
第7代,最小适应度为:-12.975929909868261
第8代,最小适应度为:-13.709409364446067
第9代,最小适应度为:-13.709409364446067
第10代,最小适应度为:-14.070832230733176
...
第195代,最小适应度为:-19.726396004677348
第196代,最小适应度为:-19.726396004677348
第197代,最小适应度为:-19.726396004677348
第198代,最小适应度为:-19.726396004677348
第199代,最小适应度为:-19.726396004677348
最优解空间为:
1.9578436000419988 -1.9990331025187396 1.9319300848728265 -1.9936739862448478
5.总结
根据对照得出,算法最后是朝着最优的方向进行的,得出来的最优解并不是真的最小值,只是一直无限的接近最小值。
GA算法还有其他的改进方法,比如交叉的方式、变异的数量、个体的取舍、并行遗传等等