目录
声明
这来源于本人的Java课程设计作品,因为觉得其有一定的实用价值,只是作为作业交上去有些可惜,故决定在CSDN平台分享出来,或许能帮助到更多的人。这也是本人第一次在社交平台上发布文章,不足之处请见谅,并欢迎友好交流与指正。
一、差分进化算法绪论
差分进化算法(Differential Evolutian,以下简称DE)是一种新兴的进化计算技术,它保留了基于种群的全局搜索策略,采用实数编码、基于差分的简单变异操作和“一对一”的竞争生存策略,降低了进化计算操作的复杂性。同时其特有的记忆能力使其可以动态跟踪当前的搜索情况,以使其调整搜索策略。
它具有较强的全局收敛能力和鲁棒性(也称稳健性),且不需要借助问题的特征信息,适用于求解一些利用常规的数学规划方法很难求解甚至无法求解的复杂优化问题。目前,DE算法已经在许多领域得到了应用,如人工神经元网络、电力、机械设计、机器人、信号处理、运筹学等。
1 基本差分进化算法
基本DE算法流程图如下:
各个步骤具体如下:
1.1初始化
DE算法利用Np个维数为D的实数值参数向量,将它们作为每一代的种群,每个个体表示为
式中:i表示个体在种群中的序列;G表示进化代数,Np表示种群规模。
为了建立优化搜索的初始点,种群必须被初始化。设参数变量的界限为:
则有:
式中,rand[0,1]表示在[0,1]之间产生的均匀随机数。
1.2变异
对于每个目标向量,基本差分进化算法的变异向量由下式产生:
式中:随机选择的序号r1、r2、r3互不相同,且与i也不同。变异算子F是一个实常数因数,它控制偏差变量的缩放,通常取值范围为[0,1]。
1.3变异
为了增加干扰参数向量的多样性,引入交叉操作,则试验向量变为:
式中:rand(j)表示产生[0,1]之间随机数发生器的第j个估计值;rnbr(i)表示产生(1,2,…,D)序列中的一个随机数,用它来确保试验向量至少从变异向量获得一个参数;CR表示交叉算子,其取值范围为[0,1]。
1.4边界处理
在有边界约束的问题中,必须保证产生新个体的参数值位于问题的可行域中,一个简单方法是将不符合边界约束的新个体用在可行域中随机产生的参数向量代替,即若:
那么有:
1.5选择
为决定试验向量是否会成为下一代的成员,DE算法按照贪婪准则将试验向量与当前种群中的目标向量进行比较。如果目标函数要被最小化,那么具有较小目标函数值的向量将在下一代种群中出现。注意:在DE算法选择程序中,试验向量只与一个个体相比较,而不是与现有种群中的所有个体相比较。
2 几种改进形式
2.1变异操作
以DE/x/y/z表示DE算法的几个变形形式。其中x限定当前变异的向量是“随机的”或“最佳的”;y是所利用的差向量的个数;z表示交叉程序的操作方法。本次设计所采用的交叉操作都是基于二项式分布的交叉操作,表示为“bin”。
利用这个表示方法,基本差分进化算法策略可描述为DE/rand/1/bin,该策略有助于种群的多样性提高,相应的,其收敛性会降低。其他常见的两种形式如下:
(1)DE/best/1/bin
best代表着种群最优位置,在上式中起着指导作用,有助于算法的局部开发能力,能够提升算法的收敛性。
(2)DE/rand-to-best/1/bin
上式在多样性和收敛性之间的制衡效果较好。两个随机位置用于开发,最优位置用来指导。
2.2变异算子
基本差分进化算法在搜索过程中变异算子取实常数,实施中变异算子较难确定:变异率太大,算法搜索效率低下,所得的全局最优解精度低;变异率太小,种群多样性降低,易出现“早熟”现象。因此可设计具有自适应变异算子的DE算法,根据算法搜索进展情况,自适应变异算子可设计如下:
式中,F0代表变异算子,Gm表示最大进化代数,G表示当前进化代数。在算法开始时自适应变异算子为2F0,具有较大值,在初期保持个体多样性,避免“早熟”;随着算法的进展,变异算子逐步降低,到后期变异概率接近F0,保留优良信息,避免最优解遭到破坏,增加搜索到全局最优解的概率。
变异操作和变异算子的策略可进行组合选择。
二、方案设计
1 整体设计框架
以进化类算法中常提及的概念——“种群”,作为主类,用于创建和解决优化问题对象。通常来说,优化问题可分为无约束优化问题和有约束优化问题两大类(在此处并不视作边界条件为约束),无约束优化问题中的许多基本方法,都被解决有约束优化问题所采用。故考虑先以无约束的基本种群——BasicPopulation,作为解决无约束优化问题的主类。然后以约束种群——ResPopulation,作为解决有约束优化问题的主类,继承基本种群中的通用属性与大多数方法,再改写和新增适用其自身的特有方法。其余的类和接口的设计都围绕这两大主类的需求而展开。
2 无约束优化类设计
2.1属性部分
这里用到另外的两个类BestRecord、EvaluateStrategy,分别用于保留最优记录和创建所需的适应度评价对象,其UML图表示如下:
2.2方法部分
2.3完整代码
import java.util.Random;
public class BasicPopulation implements MutateOperator,CrossOperator,SelectOperator {
/*基本种群,只有边界条件约束*/
/*---------------------------------------差分进化算法中的主要参数-------------------------------------------*/
public int popSize = 50; /*种群数量(默认为50)*/
public int popDim; /*变量维度*/
public int gen = 300; /*进化代数(默认为300)*/
public double[][] popState; /*目前种群样态*/
public double[] stateRecord; /*目前种群的适应度记录值*/
public double[][] popMutate; /*变异种群*/
public double[][] popTest; /*试验种群*/
public double[] testRecord; /*试验种群的适应度记录值*/
public double F = 0.4; /*变异算子(默认为0.4)*/
public String Ftype = "constant"; /*变异算子类型,默认为恒定值*/
public String mutateStrategy = "rand"; /*变异操作类型,默认为de/rand/1/bin*/
public double CR = 0.1; /*交叉算子(默认为0.1)*/
public double[] upperBound; /*上限*/
public double[] lowerBound; /*下限*/
public double[] startPoint; /*初始迭代点*/
public int[] isInteger; /*整数类型判断*/
public BestRecord best; /*最优记录*/
public EvaluateStrategy eval; /*适应度评价函数对象*/
public String objectiveSense = "min"; /*目标优化类型,默认类型为最小值型*/
public BasicPopulation(int popDim, double[] upperBound, double[] lowerBound) {
/*构造方法,给出所求变量维度及上下限*/
this.popDim = popDim;
this.upperBound = upperBound;
this.lowerBound = lowerBound;
}
public BasicPopulation() {
/*构造方法之二,用于初始化对象*/
}
/*---------------------------------------差分进化算法的主要方法流*--------------------------------------------*/
public double[][] initialize() {
/*种群初始化*/
int i, j;
Random r = new Random();
if (startPoint == null)
for (i = 0; i < popSize; i++) {
for (j = 0; j < popDim; j++) {
popState[i][j] = lowerBound[j] + r.nextDouble() * (upperBound[j] - lowerBound[j]);
}
}
else /*基于给定初始值初始化*/
for (i = 0; i < popSize; i++) {
for (j = 0; j < popDim; j++) {
if (i < popSize/2)
popState[i][j] = lowerBound[j] + r.nextDouble() * (upperBound[j] - lowerBound[j]);
else
{
double temp = r.nextBoolean() ? upperBound[j] : lowerBound[j];
popState[i][j] = startPoint[j] + 0.1*r.nextDouble() * (temp - startPoint[j]);
}
}
}
return popState;
}
public double[][] mutate(int G){
/*变异操作*/
double F;
F = this.F;
if (Ftype == "adaptive"){/*自适应变异算子*/
double lambda;
lambda = Math.exp(1-(double)(gen)/(gen-G));
F = this.F*Math.pow(2,lambda);
}
switch (mutateStrategy){
case "rand":
popMutate = deRand1(F);
break;
case "best":
popMutate = deBest1(F);
break;
case "rand2best":
popMutate = deRandToBest1(F);
break;
default:
System.out.print("请输入正确的变异类型!/n");
}
return popMutate;
}
public double[][] cross() {
/*交叉操作*/
int i, j, posi;
double posj;
Random r = new Random();
for (i = 0; i < popSize; i++) {
posi = r.nextInt(popDim);
for (j = 0; j < popDim; j++) {
posj = r.nextDouble();
if (j == posi || posj <= CR)
popTest[i][j] = popMutate[i][j];
else
popTest[i][j] = popState[i][j];
}
}
return popTest;
}
public double[][] checkBound() {
/*边界处理*/
int i, j;
Random r = new Random();
for (i = 0; i < popSize; i++) {
for (j = 0; j < popDim; j++) {
if (popTest[i][j] > upperBound[j] || popTest[i][j] < lowerBound[j])
popTest[i][j] = lowerBound[j] + r.nextDouble() * (upperBound[j] - lowerBound[j]);
}
}
return popTest;
}
public void fitness(){
/*计算当前种群和试验种群的适应度值*/
int i;
for (i = 0; i < popSize; i++) {
stateRecord[i] = eval.evalFunc(popState[i]);
testRecord[i] = eval.evalFunc(popTest[i]);
}
}
public double[][] select() {
/*选择操作***待扩容*/
int i;
if (objectiveSense == "min") {
for (i = 0; i < popSize; i++) {
if (stateRecord[i] > testRecord[i]) {
popState[i] = popTest[i].clone();
stateRecord[i] = testRecord[i];
}
}
}
else if (objectiveSense == "max"){
for (i = 0; i < popSize; i++) {
if (stateRecord[i] < testRecord[i]) {
popState[i] = popTest[i].clone();
stateRecord[i] = testRecord[i];
}
}
}
else
System.out.print("请输入正确的目标优化类型");
return popState;
}
public BestRecord record() {
/*记录最优值与最优个体*/
int i;
double temp;
best.bestIndividual = popState[0].clone();
best.bestValue = stateRecord[0];
if (objectiveSense == "min"){
for (i = 1; i < popSize; i++) {
temp = stateRecord[i];
if (temp < best.bestValue) {
best.bestValue = temp;
best.bestIndividual = popState[i].clone();
}
}
}
else if (objectiveSense == "max"){
for (i = 1; i < popSize; i++) {
temp = stateRecord[i];
if (temp > best.bestValue) {
best.bestValue = temp;
best.bestIndividual = popState[i].clone();
}
}
}
else
System.out.print("请输入正确的优化目标类型");
return best;
}
public void setIsInteger(){
/*若setInteger未赋值,则默认为0,即个体所有分量都为实数型*/
if (isInteger == null){
isInteger = new int[popDim];
}
}
public void rectify(double[][] pop){
/*混合整数规划用,将个体的某个分量转化为伪整数类型*/
int i,j;
for (i = 0;i < popDim;i++){
if (isInteger[i] == 1)
for (j = 0;j < popSize;j++){
pop[j][i] = Math.round(pop[j][i]);
}
}
}
public BestRecord solve() {
/*差分进化迭代*/
int G;
popState = new double[popSize][popDim];
popMutate = new double[popSize][popDim];
popTest = new double[popSize][popDim];
stateRecord = new double[popSize];
testRecord = new double[popSize];
best = new BestRecord();
setIsInteger();
popState = initialize();
rectify(popState);
fitness();
best = record();
for (G = 0; G < gen; G++) {
popMutate = mutate(G);
popTest = cross();
popTest = checkBound();
rectify(popTest);
fitness();
popState = select();
best = record();
}
best = record();
return best;
}
/*-------------------------------------差分进化算法中的辅助方法(供主要方法调用)----------------------------------*/
public double[][] deRand1(double F) {
/*DE/rand/1/bin型变异操作*/
int i, j;
int[] seqr;
for (i = 0; i < popSize; i++) {
seqr = unrepeatSeq3();
for (j = 0; j < popDim; j++) {
popMutate[i][j] = popState[seqr[0]][j] + F * (popState[seqr[1]][j] - popState[seqr[2]][j]);
}
}
return popMutate;
}
public double[][] deBest1(double F) {
/*DE/rand/1/bin型变异操作*/
int i, j;
int[] seqr;
for (i = 0; i < popSize; i++) {
seqr = unrepeatSeq2();
for (j = 0; j < popDim; j++) {
popMutate[i][j] = best.bestIndividual[j] + F * (popState[seqr[0]][j] - popState[seqr[1]][j]);
}
}
return popMutate;
}
public double[][] deRandToBest1(double F) {
/*DE/rand/1/bin型变异操作*/
int i, j;
int[] seqr;
for (i = 0; i < popSize; i++) {
seqr = unrepeatSeq2();
for (j = 0; j < popDim; j++) {
popMutate[i][j] = popState[i][j] + F * (best.bestIndividual[j]-popState[i][j]) +
F * (popState[seqr[0]][j] - popState[seqr[1]][j]);
}
}
return popMutate;
}
public int[] unrepeatSeq3() {
/*产生3个不重复随机整数,用于de/rand/1/bin*/
int i, temp;
Random r = new Random();
int[] seq = new int[3];
seq[0] = r.nextInt(popSize);
for(i = 1;i < 3;i++){
temp = r.nextInt(popSize);
while (isin(seq,temp)){
temp = r.nextInt(popSize);
}
seq[i] = temp;
}
return seq;
}
public int[] unrepeatSeq2(){
/*产生2个不重复随机整数,用于de/best/1/bin、de/rand to best/1/bin*/
int i, temp;
Random r = new Random();
int[] seq = new int[2];
seq[0] = r.nextInt(popSize);
for(i = 1;i < 2;i++){
temp = r.nextInt(popSize);
while (isin(seq,temp)){
temp = r.nextInt(popSize);
}
seq[i] = temp;
}
return seq;
}
public boolean isin(int[] ary,int val){
/*检查数组中是否包含给定元素,供随机数组的产生使用*/
int n = ary.length;
int i;
boolean found = false;
for (i = 0;i < n;i++){
if (ary[i] == val) {
found = true;
break;
}
}
return found;
}
}
/*----------------聚合的类和实现的接口---------------*/
public class BestRecord {/*最优记录类*/
double bestValue;
double [] bestIndividual;
}
public abstract class EvaluateStrategy implements EvaluateFunction{/*评价函数类*/
public abstract double evalFunc(double[] individual);
public double score = 0;
}
public interface EvaluateFunction {
public abstract double evalFunc(double[] individual);
}
public interface CrossOperator {
double[][] cross();
}
public interface MutateOperator {
public abstract double[][] mutate(int G);
}
public interface SelectOperator {
public abstract double[][]select();
}
3 含约束优化类设计
一般地,含约束项的优化问题的数学形式可如下表示:
其中,A和Aeq是矩阵,b和beq是向量,它们与x所构成的表达式代表着所有的线性约束。c(x)和ceq(x)是返回向量值的非线性函数,它们代表着所有的线性约束。f(x)则是返回标量值的目标函数。
与先前的无约束优化问题相比,包含了约束性后,问题的处理显然将更为复杂。除了目标函数值需尽可能往最优值方向前进的同时,还需时刻检查其是否位于约束项所包围的可行域内,这样将使程序更为复杂且运行效率低下。为此不妨试着考虑将包含约束项的优化问题转变成去约束的优化问题,这样便能继续采用先前的无约束优化问题的处理方法。这便是下面所将介绍的罚函数法的基本思路。
3.1罚函数法
将求解待约束非线性优化问题转化为一系列无约束极值问题,因而也称这种方法为序列无约束最小化方法(Sequential Unconstrained Minization Technique,SUMT)。在搜索求解过程中,对企图违反约束的那些点给出相应的惩罚,迫使这一些列的点向可行域靠近,直到收敛到原问题的最优解为止,这便是罚函数法的基本思想与操作。
作线性惩罚函数Pl如下,它用来记录违反线性约束的惩罚值。
其中Ai、Aeqi为矩阵A、Aeq的第i行,bi、beqi为向量b、beq的第i个分量。
作非线性惩罚函数Pnl如下,它用来记录违反非线性约束的惩罚值。
其中ci(x)、ceqi(x)代表c(x)、ceq(x)的第i个约束表达式分量。
则总的惩罚函数如下所示
由此便可构建等价的无约束化优化问题模型如下
3.2属性部分
新增一抽象类NonlinearConstraint,其UML图如下
其中属性lenum记录不等式非线性约束的个数,eqnum记录等式线性约束的个数,out为长度为2的二维数组,out[0]、out[1]两个一维数组分别记录目标非线性约束项c(x)、ceq(x)的各分量值。方法nonlcon为非线性约束函数,输入参数为个体,返回out数组。
3.3方法部分
3.4完整代码
public class ResPopulation extends BasicPopulation{
/*----------------------------------------------约束属性定义-------------------------------------------------*/
/*附有其他的线性与非线性约束*/
double[][] A; /*线性约束*/
double[] b;
double[][] Aeq;
double[] beq;
double M = 1e5; /*罚因子(默认为10000)*/
double th = 1e-3; /*约束阈限*/
double startBundle = 1; /*收束启用条件*/
double [] statePunish; /*当前种群的惩罚值*/
double [] testPunish; /*试验种群的惩罚值*/
double [] stateSynthesis; /*当前种群的综合得分*/
double [] testSynthesis; /*试验种群的综合得分*/
NonlinearConstraint C; /*非线性约束*/
String problemType = "mixed"; /*问题类型,默认同时包含线性与非线性约束*/
public ResPopulation(int popDim, double[][] A, double[]b, double[] upperBound, double[] lowerBound){
/*构造方法之一,A型构造*/
this.popDim = popDim;
this.A = A;
this.b = b;
Aeq = new double[1][popDim];
beq = new double[popDim];
this.upperBound = upperBound;
this.lowerBound = lowerBound;
}
public ResPopulation(int popDim, double[] upperBound, double[] lowerBound,double[][] Aeq,double[] beq){
/*构造方法之二,Aeq型构造*/
this.popDim = popDim;
A = new double[1][popDim];
b = new double[popDim];
this.Aeq = Aeq;
this.beq = beq;
this.upperBound = upperBound;
this.lowerBound = lowerBound;
}
public ResPopulation(int popDim,double[][] A,double[] b,double[] upperBound,
double[] lowerBound,double[][] Aeq,double[] beq){
/*构造方法之三,A,Aeq型构造*/
this.popDim = popDim;
this.upperBound = upperBound;
this.lowerBound = lowerBound;
this.A = A;
this.b = b;
this.Aeq = Aeq;
this.beq = beq;
}
public ResPopulation(int popDim,double[] upperBound,double[] lowerBound){
/*构造方法之四,C型构造*/
this.popDim = popDim;
this.upperBound = upperBound;
this.lowerBound = lowerBound;
A = new double[1][popDim];
b = new double[popDim];
Aeq = new double[1][popDim];
beq = new double[popDim];
}
public ResPopulation(){
/*构造方法之五,用于初始化对象*/
}
/*---------------------------------------基于障碍函数法去约束化求最优值-------------------------------------------*/
@Override
public double[][] select(){
int i;
if (objectiveSense == "min"){
for (i = 0;i < popSize;i++){
if (stateSynthesis[i] > testSynthesis[i]){
popState[i] = popTest[i].clone();
stateSynthesis[i] = testSynthesis[i];
}
}
}
else if (objectiveSense == "max"){
for (i = 0;i < popSize;i++){
if (stateSynthesis[i] < testSynthesis[i]){
popState[i] = popTest[i].clone();
stateSynthesis[i] = testSynthesis[i];
}
}
}
else
System.out.print("请输入正确的优化目标类型");
return popState;
}
@Override
public BestRecord record() {
/*记录最优值与最优个体*/
int i;
double temp;
best.bestIndividual = popState[0].clone();
best.bestValue = stateSynthesis[0];
if (objectiveSense == "min"){
for (i = 1; i < popSize; i++) {
temp = stateSynthesis[i];
if (temp < best.bestValue) {
best.bestValue = temp;
best.bestIndividual = popState[i].clone();
}
}
}
else if (objectiveSense == "max"){
for (i = 1; i < popSize; i++) {
temp = stateSynthesis[i];
if (temp > best.bestValue) {
best.bestValue = temp;
best.bestIndividual = popState[i].clone();
}
}
}
else
System.out.print("请输入正确的优化目标类型");
return best;
}
public void punishment(){
/*计算惩罚值*/
switch (problemType){
case "linear":
linprog();
break;
case "nonliner":
nonlinprog();
break;
case "mixed":
mixprog();
break;
default:
System.out.print("请选择正确的问题类型");
}
}
public void syntheScore(){
/*计算综合得分*/
int i;
if (objectiveSense == "min") {
for (i = 0; i < popSize; i++) {
stateSynthesis[i] = stateRecord[i] + statePunish[i];
testSynthesis[i] = testRecord[i] + testPunish[i];
}
}
else if (objectiveSense == "max") {
for (i = 0; i < popSize; i++) {
stateSynthesis[i] = stateRecord[i] - statePunish[i];
testSynthesis[i] = testRecord[i] - testPunish[i];
}
}
else
System.out.print("请输入正确的优化目标类型");
}
public void dynamicAdjust(){
/*区间动态收敛方法*/
int i,j;
double[] min = popState[0].clone(),max = popState[0].clone();
for (i = 0;i < popDim;i++){
for (j = 1;j < popSize;j++){
if (min[i] > popState[j][i])
min[i] = popState[j][i];
if (max[i] < popState[j][i])
max[i] = popState[j][i];
}
}
lowerBound = min.clone();
upperBound = max.clone();
}
@Override
public BestRecord solve() {
/*重写差分进化迭代,避免同名父类覆盖*/
int G;
popState = new double[popSize][popDim];
popMutate = new double[popSize][popDim];
popTest = new double[popSize][popDim];
stateRecord = new double[popSize];
testRecord = new double[popSize];
statePunish = new double[popSize];
testPunish = new double[popSize];
stateSynthesis = new double[popSize];
testSynthesis = new double[popSize];
best = new BestRecord();
setIsInteger();
popState = initialize();
rectify(popState);
fitness();
punishment();
syntheScore();
best = record();
for (G = 0; G < gen; G++) {
popMutate = mutate(G);
popTest = cross();
popTest = checkBound();
rectify(popTest);
fitness();
punishment();
syntheScore();
popState = select();
best = record();
if (G > (int)(gen*startBundle))
dynamicAdjust();
}
best = record();
best.bestValue = eval.evalFunc(best.bestIndividual);
return best;
}
/*----------------------------------------------punishment的三种形态----------------------------------------------*/
public void mixprog(){
/*混合约束*/
int i,j,k;
double ltemp1,ltemp2,ltemp11,ltemp22; /*线性约束惩罚值暂存*/
double nltemp1,nltemp2,nltemp11,nltemp22,nltemp = 0; /*非线性约束惩罚值暂存*/
for (i = 0;i < popSize;i++){
ltemp1 = 0;
ltemp2 = 0;
nltemp1 = 0;
nltemp2 = 0;
for (j = 0;j < A.length;j++){/*Ax≤b惩罚项*/
ltemp11 = 0;
ltemp22 = 0;
for (k = 0;k < popDim;k++){
ltemp11 += A[j][k]*popState[i][k];
ltemp22 += A[j][k]*popTest[i][k];
}
ltemp11 -= b[j];
ltemp22 -= b[j];
if (ltemp11 < 0)
ltemp11 = 0;
if (ltemp22 < 0)
ltemp22 = 0;
ltemp1 += Math.pow(ltemp11,2);
ltemp2 += Math.pow(ltemp22,2);
}
for (j = 0;j < Aeq.length;j++){/*Aeqx=beq惩罚项*/
ltemp11 = 0;
ltemp22 = 0;
for (k = 0;k < popDim;k++){
ltemp11 += Aeq[j][k]*popState[i][k];
ltemp22 += Aeq[j][k]*popTest[i][k];
}
ltemp11 -= beq[j];
ltemp22 -= beq[j];
if (Math.abs(ltemp11) < th)
ltemp11 = 0;
if (Math.abs(ltemp22) < th)
ltemp22 = 0;
ltemp1 += Math.pow(ltemp11,2);
ltemp2 += Math.pow(ltemp22,2);
}
if (C.lenum != 0) /*不等式约束惩罚项*/{
nltemp11 = 0;
nltemp22 = 0;
for (j = 0;j < C.lenum;j++) {
nltemp = C.nonlcon(popState[i])[0][j];
if (nltemp < 0)
nltemp = 0;
nltemp11 += Math.pow(nltemp,2);
nltemp = C.nonlcon(popTest[i])[0][j];
if (nltemp < 0)
nltemp = 0;
nltemp22 += Math.pow(nltemp,2);
}
nltemp1 += nltemp11;
nltemp2 += nltemp22;
}
if (C.eqnum != 0)/*等式约束惩罚项*/ {
nltemp11 = 0;
nltemp22 = 0;
for (j = 0; j < C.eqnum; j++) {
nltemp = C.nonlcon(popState[i])[1][j];
if (Math.abs(nltemp) < th)
nltemp = 0;
nltemp11 += Math.pow(nltemp,2);
nltemp = C.nonlcon(popTest[i])[1][j];
if (Math.abs(nltemp) < th)
nltemp = 0;
nltemp22 += Math.pow(nltemp,2);
}
nltemp1 += nltemp11;
nltemp2 += nltemp22;
}
statePunish[i] = M*(ltemp1+nltemp1);
testPunish[i] = M*(ltemp2+nltemp2);
}
}
/*----------------聚合的类和实现的接口---------------*/
public abstract class NonlinearConstraint implements NonlinearConFunc{
public abstract double[][] nonlcon(double[] individual);
public int lenum = 0; /*不等式非线性约束数,默认为0*/
public int eqnum = 0; /*等式非线性约束数,默认为0*/
}
public interface NonlinearConFunc {
public abstract double[][] nonlcon(double[] individual);
}
三、案例测试
1.Rastrigin函数
该函数图像如下:
其有全局最小值0,并位于点(0,0)处
代码构建如下:
import java.util.Arrays;
public class ProbSolve {
public static void main(String args[]){
/*解决最优化问题的模板流*/
/*1st:创建优化对象,设置相关基本信息*/
long startTime=System.currentTimeMillis();/*获取开始时间*/
BasicPopulation problem = new BasicPopulation();
int dim = 2; //变量维度
double[][] bound = {{50,50},{-50,-50}};
problem.popDim = dim; //优化变量维度
problem.upperBound = bound[0]; //边界上限
problem.lowerBound = bound[1]; //边界下限
/*2nd:定义优化目标*/
EvaluateStrategy evaluate;
evaluate = new Rosenbrock(); //创建适应度评价对象
problem.eval = evaluate;
/*3rd:设置相关优化选项(该步骤可根据需要选择是否进行)*/
/*problem.gen = 200; //进化代数
problem.popSize = 50; //种群规模
problem.Ftype = "adaptive"; //自适应变异算子策略
problem.F = 0.4;*/ //变异算子
problem.mutateStrategy = "best"; //变异操作
double[] init = {1,1};
problem.startPoint = init; //迭代起始点
/*4th:进行优化迭代、结果保存及输出*/
//problem.Ftype = "adaptive";
BestRecord best;
best = problem.solve();
System.out.println(best.bestValue);
System.out.println(Arrays.toString(best.bestIndividual));
long endTime=System.currentTimeMillis(); //获取结束时间
System.out.println("程序运行时间: "+(endTime-startTime)+"ms");
}
}
/*此处Rastrigin函数作为外部类*/
public class Rastrigin extends EvaluateStrategy{
public double evalFunc(double[] x){
int i,n;
double out = 0;
n = x.length;
for (double temp:x){
out += Math.pow(temp,2)-10*Math.cos(2*Math.PI*temp)+10;
}
score = out;
return score;
}
}
运行结果如下:
2.Rosenbrock函数
其函数图像如下:
其有全局最小值0.位于点(0,0)处。
对该函数寻优,只需在“定义优化目标”中将目标函数进行修改而已。其他的和Rastrigin实例基本一致。代码修改部分如下:
public class Rosenbrock extends EvaluateStrategy{
/*香蕉函数,测试优化算法性能的非凸函数*/
public double evalFunc(double[] x){
int n = x.length;
int i = 0;
double out = 0;
for (i = 0;i < n-1;i++){
out += 100*Math.pow(x[i+1]-Math.pow(x[i],2),2)+Math.pow(x[i]-1,2);
}
score = out;
return score;
}
}
EvaluateStrategy evaluate;
evaluate = new Rrosenbrock();
problem.eval = evaluate;
运行效果如下:
3.非线性约束优化问题
对于该非线性规划问题,由Matlab软件可得其有最小值3.79894655,位于点(0.55357413,1.30644509)。
代码构建如下:
1. import java.util.Arrays;
2. public class ProbMixed {
3. public static void main(String args[]){
4. /*解决非线性优化模板流*/
5. /*--------------1st:定义优化问题及线性约束范围--------------*/
6. ResPopulation problem; /*创建优化问题对象*/
7. BestRecord sol; /*创建优化记录对象*/
8. int dim = 2; /*设置变量维度*/
9. double[][] A = {{-1,1}}; /*赋值系数矩阵A*/
10. double[] b = {2}; /*赋值增广列向量b*/
11. /*double[][] Aeq = new double[0][0];
12. double[] beq = new double[0];*/
13. double[] lowerBound = {0,0}; /*定义下限*/
14. double[] upperBound = {100000,100000}; /*定义上限*/
15. /*---------------2rd:定义适应度函数以及非线性约束*----------------*/
16. class Instance extends NonlinearConstraint{
17. /*用内部类创建非线性约束对象*/
18. public double[][] nonlcon(double[] x){
19. double[][] out = new double[1][1];
20. out[0][0] = Math.pow(x[0],2)-x[1]+1; /*不等式约束标准写法*/
21. return out;
22. }
23. }
24. NonlinearConstraint Con = new Instance(); /*利用上转型对象实现非线性约束对象的创立*/
25. Con.lenum = 1; /*设置非线性不等式约束个数*/
26. class objfun extends EvaluateStrategy{
27. /*用内部类创建适应度评价对象*/
28. public double evalFunc(double[] x){
29. score = Math.pow(x[0],2)+Math.pow(x[1],2)-4*x[0]+4;
30. return score;
31. }
32. }
33. EvaluateStrategy obj = new objfun(); /*利用上转型对象实现适应度评价对象的建立*/
34. problem = new ResPopulation(dim,A,b,upperBound,lowerBound);//,Aeq,beq);
35. problem.C = Con;
36. problem.eval = obj;
37. /*---------------3th:设置差分进化算法的相应参数,解决优化问题---------------*/
38. problem.gen = 1000; /*进化代数*/
39. problem.popSize = 50; /*种群大小*/
40. problem.M = 1e4; /*惩罚数*/
41. problem.Ftype = "adaptive";/*自适应变异算子*/
42.
43. problem.F = 0.4;
44. problem.mutateStrategy = "best";/*DE/best/1/bin策略*/
45. problem.problemType = "mixed"; /*问题的约束类型*/
46. sol = problem.solve(); /*迭代求解,得到最优值与最优个体*/
47. System.out.println(sol.bestValue);
48. System.out.println(Arrays.toString(sol.bestIndividual));
49. }
50. }
51.
结果输出如下
4.非线性混合整数规划问题(MINP)
该规划问题在Matlab可求得其最小值点(1,4.7430,3.8211,1.3794),和最小值17.0140。
代码构建如下:
1. import java.util.Arrays;
2. public class ProbMixedInteger {
3. public static void main(String args[]){
4. /*解决MINP问题模板流*/
5. /*---------------1st:定义优化问题及约束范围------------------*/
6. ResPopulation problem; /*创建优化问题对象*/
7. BestRecord sol; /*创建优化记录对象*/
8. long startTime=System.currentTimeMillis();/*获取开始时间*/
9. int dim = 4; /*设置变量维度*/
10. double[] lowerBound = {1,1,1,1}; /*定义下限*/
11. double[] upperBound = {5,5,5,5}; /*定义上限*/
12. int[] isint = {1,0,0,0}; /*定义整数变量,第一个分量为1,代表其为整数*/
13. /*---------------2rd:定义适应度函数以及非线性约束*---------------*/
14. class Instance extends NonlinearConstraint{
15. /*用内部类创建非线性约束对象*/
16. public double[][] nonlcon(double[] x){
17. double[][] out = new double[2][1];
18. out[0][0] = -x[0]*x[1]*x[2]*x[3]+25; /*不等式约束标准写法*/
19. out[1][0] = Math.pow(x[0],2)+Math.pow(x[1],2)+Math.pow(x[2],2)+Math.pow(x[3],2)-40;
20. return out;
21. }
22. }
23. NonlinearConstraint Con = new Instance(); /*利用上转型对象实现非线性约束对象的创立*/
24. Con.lenum = 1; /*设置非线性不等式约束个数*/
25. Con.eqnum = 1; /*设置非线性等式约束个数*/
26. class objfun extends EvaluateStrategy{
27. /*用内部类创建适应度评价对象*/
28. public double evalFunc(double[] x){
29. score = x[0]*x[3]*(x[0]+x[1]+x[2])+x[2];
30. return score;
31. }
32. }
33. EvaluateStrategy obj = new objfun(); /*利用上转型对象实现适应度评价对象的建立*/
34. problem = new ResPopulation(dim,upperBound,lowerBound);//,Aeq,beq);
35. problem.C = Con;
36. problem.eval = obj;
37. /*-----------3th:设置差分进化算法的相应参数,解决优化问题----------*/
38. problem.M = 1e4; /*惩罚数*/
39. problem.th = 1e-5; /*阈限*/
40. problem.popSize = 100;
41. problem.gen = 7000;
42. problem.Ftype = "adaptive";
43. problem.mutateStrategy = "best";
44. sol = problem.solve(); /*迭代求解,得到最优值与最优个体*/
45. long endTime=System.currentTimeMillis(); //获取结束时间
46. System.out.println(sol.bestValue);
47. System.out.println(Arrays.toString(sol.bestIndividual));
48. System.out.println("程序运行时间: "+(endTime-startTime)+"ms");
49. }
50. }
运行结果如下: