带约束条件的差分进化算法(python实现)

来源:互联网 发布:手机淘宝促销活动 编辑:程序博客网 时间:2024/05/24 05:14

  看这篇文章之前,读者应已经理解差分进化算法。

  用python写带约束条件的差分进化的代码时,我参考了别人不带约束条件的代码。我解决的问题如下图所示。

  

  我得到的结果如下

  

  -14.98869与-15差一点,不过算是找到了f(x)的最小值。对应的向量也与(1,1,1,1,1,1,1,1,1,3,3,3,1)差不多。

  我的代码如下:

 # -*- coding: cp936 -*-
import pdb
import g01
import matplotlib.pyplot as plt
global Gm,F0,Np,CR,D
Gm=500
F0=0.5
Np=130
CR=0.2
G=1
D=13
from numpy import *
import numpy as np
V=np.zeros((Np,D))
U=np.zeros((Np,D))
XG_next=np.zeros((Np,D))
value=np.zeros(Np)
cv=np.zeros(Np)
cv[:]=1000
##############产生初始种群############
from numpy import random
max0=1
max1=100
min0=0
min1=0
X0=random.random(size=(Np,D))
for i in range(9):
    X0[:,i]=X0[:,i]*(max0-min0)+min0
for i in range(9,12):
    X0[:,i]=X0[:,i]*(max1-min1)+min1
X0[:,12]=X0[:,12]*(max0-min0)+min0
XG=X0


while G<=Gm:
    print G
    ####################变异操作###################
    for i in range(1,Np):
        li=range(Np)
        random.shuffle(li)
        dx=li
        j=dx[0]
        k=dx[1]
        p=dx[2]
        #要保证与i不同
        if j==i:
            j=dx[3]
        elif k==i:
            k=dx[3]
        elif p==i:
            p=dx[3]
        #变异操作
        suanzi=math.exp(1-float(Gm)/(Gm+1-G))
        F=F0*(2**suanzi)
        mutant=XG[p]+F*(XG[j]-XG[k])
        for j in range(9):
            if mutant[j]>min0 and mutant[j]<max0:
                V[i,j]=mutant[j]
            else:
                V[i,j]=(max0-min0)*random.rand()+min0
        for j in range(9,12):
            if mutant[j]>min1 and mutant[j]<max1:
                V[i,j]=mutant[j]
            else:
                V[i,j]=(max1-min1)*random.rand()+min1
        if mutant[12]>min0 and mutant[12]<max0:
                V[i,12]=mutant[12]
        else:
            V[i,12]=(max0-min0)*random.rand()+min0
    #######################交叉操作#####################
    
    for i in range(Np):
        randx=range(D)
        random.shuffle(randx)
        for j in range(D):
            if random.rand()>CR and randx[0]!=j:
                U[i,j]=XG[i,j]
            else:
                U[i,j]=V[i,j]
    ########################选择操作######################
    for i in range(Np):
        f1=g01.f(XG[i])
        f2=g01.f(U[i])
        g1=g01.g(XG[i])
        g2=g01.g(U[i])
        if g1==0 and g2==0:
            if f1<f2:
                XG_next[i]=XG[i]
            else:
                XG_next[i]=U[i]
        elif g1==0 or g2==0:
            if g1==0:
                XG_next[i]=XG[i]
            else:
                XG_next[i]=U[i]
        elif g1!=0 and g2!=0:
            if g1<g2:
                XG_next[i]=XG[i]
            else:
                XG_next[i]=U[i]
    XG=XG_next
    G=G+1
for i in range(Np):
    cv[i]=g01.g(XG[i])
    if abs(cv[i]-0)<0.05:
        value[i]=g01.f(XG[i])
best_value=min(value)
temp=value.tolist()
pos_min=temp.index(min(temp))
print best_value
best_vector=XG[pos_min]
print best_vector


  我写的函数在另一个叫g01.py的文件里,这个文件是对问题的描述,代码如下。

def f(v):
    import math
    y=5*(v[0]+v[1]+v[2]+v[3])-5*(v[0]**2+v[1]**2+v[2]**2+v[3]**2)-\
       (v[4]+v[5]+v[6]+v[7]+v[8]+v[9]+v[10]+v[11]+v[12])
    return y


def g(v):
    import math
    g1=2*v[0]+2*v[1]+v[9]+v[10]-10
    g2=2*v[0]+2*v[2]+v[9]+v[11]-10
    g3=2*v[1]+2*v[2]+v[10]+v[11]-10
    g4=-8*v[0]+v[9]
    g5=-8*v[1]+v[10]
    g6=-8*v[2]+v[11]
    g7=-2*v[3]-v[4]+v[9]
    g8=-2*v[5]-v[6]+v[10]
    g9=-2*v[7]-v[8]+v[11]
    g1=max(g1,0)
    g2=max(g2,0)
    g3=max(g3,0)
    g4=max(g4,0)
    g5=max(g5,0)
    g6=max(g6,0)
    g7=max(g7,0)
    g8=max(g8,0)
    g9=max(g9,0)
    g=max(g1,g2,g3,g4,g5,g6,g7,g8,g9)
    if g==0:
        cv=0
    else:
        cv=1.0/(13*g)*(g1+g2+g3+g4+g5+g6+g7+g8+g9)
    return cv

  带约束问题与不带约束问题的不同在于,前者有一系列不等式gi(x)(i=1,2,....m)对X进行了限制,所以问题的一个难点在于如何使产生的群体X满足约束条件。我们不可能直接产生这样的群体,只能不断更新群体,使其里条件更近。首先产生满足边界条件的初始种群,在这个问题中,即0<xi<1((i=1,2,3,...9),0<xi<100(i=10,11,12),0<x13<1。

  初始种群Xi(i=1,2,...Np)——>变异Vi(i=1,2,...Np)——>交叉Ui(i=1,2,...Np),接下来就是选择操作,这与不带约束条件的差分进化算法不同,我这里用到的方法如下:

  设有m个约束条件,计算每个约束条件的违约值:,比如我解决的这个问题中,第一个约束条件g1(x)=2*x1+2*x2+x10+x11-10<0,那么某一个解向量(1,1,1,1,1,1,1,1,1,3,3,3,1)对应的第一个约束条件的违约值是max(2*1+2*1+3+3-10,0)=0,函数对应的违约值为0时,对应的xi即为满足约束条件的个体。

  下面就要计算一个解向量对应的违约值了,即(1,1,1,1,1,1,1,1,1,3,3,3,1)对应的违约值,用到这个公式:,这叫向量的违约值,记为cv,cv越小,说明这个解向量越满足约束条件。所以,在进行选择操作时,我用到这样一个方法:

              

     举个例子:

    

              选择得到的新群体再进行变异,交叉选择操作,就这样迭代数次后,群体里的每个个体就越来越趋近于minimum vector了。