差分进化算法属于一种进化算法,以全局最优性、收敛速度快等特点,得到很多学者的关注,并将其扩展到参数优化、数值优化、工程优化、路径优化、机器学习等一系列研究中。
而差分进化算法的原理即过程又是什么呢?
一、什么是差分进化算法
差分进化算法的原理属于内部寻优机制,通过不断缩小搜索区域进而达到最优区域范围,使其种群不断靠近最优区域的邻域。如下图所示:
通过上图,可知种群个体不断在搜索区域搜寻,随着搜寻次数的增加,搜索区域面积在逐渐减少。最后,种群个体都朝着最优区域前进,落在邻域内,这样一个过程就完成了差分进化算法的内部进化机制。
至于差分进化算法的原理,这里就不再过多阐述。接下来将阐述如何运用java的面向对象思维,编写程序!
二、差分进化算法需要实现的方法部分
对于差分进化算法,需要经过初始化种群、保存初始种群下的当前最优值、变异、交叉、选择、保存全局最优值,因此可以将其看作面向对象的方法,其中种群中的种群数、个体、变异因子、交叉因子看作是面向对象的属性。
所以,将种群数、个体、变异因子、交叉因子编写成成员变量如下:
//初始化参数--以公共变量为主--所有方法都可以访问
public int Np=10; //种群数量
public int D=2; //个体维度---维数越高收敛度就会下降----多维函数建立
public double F=0.5; //变异因子
public double Cr=0.95; // 交叉概率 ---在这里取1收敛速度快,为什么?
public double xmax=1; //基向量的最大值 ----根据函数的自变量建立每个区间的初始值(改进)
public double xmin=-1; //基向量的最小值
将当前最优值、变异、交叉、选择、保存全局最优值看作成面向对象的方法:
// 初始化种群
public void Init(){
Random r=new Random();
double d1 = r.nextDouble();
for (int i=0;i<Np;i++)
for(int j=0;j<D;j++)
X[i][j]=xmin+(xmax-xmin)*d1;
this.setX(X);
}
//保存当前最优值
public void save_best(){
X=this.getX();
best=X[0];
for(int i=1;i<Np;i++){
if(cal_fitness(best)<cal_fitness(X[i]))
best=X[i];
}
this.setBest(best);
}
//变异操作
public void variated(){
X=this.getX();
Random r=new Random();
for(int i=0;i<Np;i++){
int r0=0,r1=0,r2=0;
for(int j=0;j<D;j++){
if(r2==i||r1==i||r0==i||r0==r1||r0==r2||r1==r2) //做基变量的的互异问题
r0=r.nextInt(Np);
r1=r.nextInt(Np);
r2=r.nextInt(Np);
V[i][j]=X[r0][j]+(X[r1][j]-X[r2][j])*F; //变异
//防止越界;检查是否越界
if(V[i][j]<xmin)
V[i][j]=xmin;
if(V[i][j]>xmax)
V[i][j]=xmax;
}
}
this.setV(V);
}
//交叉操作
public void cross(){
X=this.getX();
V=this.getV();
Random r=new Random();
for(int i=0;i<Np;i++){
for(int j=0;j<D;j++){
int jrand=r.nextInt(D);
if(r.nextDouble()<Cr || j==jrand)
U[i][j]=V[i][j];
else
U[i][j]=X[i][j];
}
}
this.setU(U);
}
// 选择操作
public void select(){
X=this.getX();
U=this.getU();
for(int i=0;i<Np;i++){
if(cal_fitness(U[i])<cal_fitness(X[i]))
X[i]=U[i];
else
X[i]=X[i];
}
this.setX(X);
}
//全局最优值保存
public void gobal_solve(){
best=this.getBest();
X=this.getX();
for(int i=0;i<Np;i++){
if(cal_fitness(X[i])<cal_fitness(best))
best=X[i];
}
this.setBest(best);
best_fitness=cal_fitness(best);
System.out.println("最优解:"+best[0]+", "+best[1]);
System.out.println("最优值:"+best_fitness);
System.out.println("----------------------------");
}
而其中不同的方法,需要进行相互调用,而创建的void方法需要对其返回值需要保存到提前开创的存储空间:
//创建储存种群的矩阵
private double X[][]=new double[Np][D]; //存放初始个体以及子代个体
private double V[][]=new double[Np][D]; // 存放变异个体
private double U[][]=new double[Np][D]; //存放交叉个体
private double best_fitness;
private double best[]=new double[D]; // 保存最优个体
/*复制个体及种群---其中的X,V,U,best_fitness,best
属于私有的属性,不能独自获取,需要创建一个公有访问方法
*/
public double[][] getX(){
return X;
}
public void setX(double[][] X){
for(int i=0;i<Np;i++)
for(int j=0;j<D;j++)
this.X[i][j]=X[i][j];
}
public double[][] getV(){
return V;
}
public void setV(double[][] V){
for(int i=0;i<Np;i++)
for(int j=0;j<D;j++)
this.V[i][j]=V[i][j];
}
public double[][] getU(){
return U;
}
public void setU(double[][] U){
for(int i=0;i<Np;i++)
for(int j=0;j<D;j++)
this.U[i][j]=U[i][j];
}
然后开创好空间、创建方法、设置成员变量之后,创建函数:
// 创建测试函数
public double cal_fitness(double x[]){
double y;
y=x[0]*x[0]+x[1]*x[1]-2;
return y;
}
函数可以根据自己的需求进行修改!
之后,创建主方法,调用各子方法,运行差分进化算法的整个过程:
public static void main(String[] args){
// 创建对象
Tradition_DE g=new Tradition_DE();
int iter=0;
g.Init();
while (iter<1000){
//g.DE();
g.variated();
g.cross();
g.select();
g.gobal_solve();
iter++;
}
}
三、运行结果
最优解:0.0, 0.0
最优值:-2.0
----------------------------
最优解:0.0, 0.0
最优值:-2.0
----------------------------
点击下方蓝色字体链接,获取源代码: