03差分进化算法

文章介绍了差分进化算法的基本原理,包括新解的生成公式和算法流程。强调了自适应λ在控制变异权重中的作用,以及其随迭代次数变化的可视化展示。此外,还提供了一个Python代码示例来演示算法的应用,并展示了算法在解决特定优化问题时的性能。
摘要由CSDN通过智能技术生成

差分进化算法

  • 差分进化算法是一种数值优化解法,研究生课程的数值分析方法中有很多类似的思想。
  • 差分进化算法最关键的公式就是产生新解的公式,使用三个旧解产生一个新解。公式如下:
    X n e w = X 1 + F ∗ ( X 2 − X 3 ) \large X_{new} = X_1 +F *(X_2-X_3) Xnew=X1+F(X2X3)

差分进化算法流程图

Alt

自适应的 λ \lambda λ

  • λ \lambda λ控制的是变异时加权差的权重;加权差又是什么,在这个算法里面,变异操作实际上就是一种差分操作。
  • 公式如下:,用三个不相同的解通过加权差加到另一个解上产生新的解。
    Alt
  • 如上公式中的F就是这个权。自适应的权需要随着迭代进程发生变化,公式如下:
    Alt
  • 这个 G m G_m Gm表示当前迭代次数,G表示最大迭代次数, F 0 F_0 F0表示初始权。
  • 可以把 λ \lambda λ画出来看一下,设置G=100,如图所示:

自适应的 λ \lambda λ可视化

Alt

  • 可以看到随着迭代次数增多, λ \lambda λ逐渐变小;意思就是随着迭代的增加,我们希望变异时,解的波动范围应该变小,从而引导解的收敛。

Python代码

f ( x ) = ∑ i = 1 n x i 2 ( − 20 ⩽ x i ⩽ 20 ) \large f(x)=\sum_{i=1}^{n} x_{i}^{2}\left(-20 \leqslant x_{i} \leqslant 20\right) f(x)=i=1nxi2(20xi20)

import numpy as np
import matplotlib.pyplot as plt
import matplotlib
from numpy import random

class DE():  # differential evolution-->DE
    def __init__(self,NP,D,G,F0,Pc,Xs,Xx,E):
        '''
        :param NP: 种群数量
        :param D: 解维度
        :param G: 最大迭代次数
        :param F0: 初始变异算子
        :param Pc: 交叉概率-->这里交叉的意思,是用一个中间变量存放可能的变异解和不发生变异的解,后面再把这个中间变量还给初始解变量
        :param Xs: 解上限
        :param Xx: 解下限
        :param E: 阈值
        '''
        self.NP = NP
        self.D = D
        self.Xs = Xs
        self.Xx = Xx
        self.E = E
        self.Pc = Pc
        self.G = G
        self.F0 = F0

    def func(self,x):
        return sum(x**2)

    def de(self):
        x = random.rand(self.NP,self.D)*(self.Xs-self.Xx) + self.Xx
        v = np.zeros((self.NP,self.D))
        u = np.zeros((self.NP,self.D))
        y = self.func(x.T)
        trace = []
        trace.append(min(y))

        g = 0
        deta = 1e-10
        while y[0] > self.E:
        # for g in range(self.G):
            ''' 变异操作'''
            # 自适应变异算子
            lamda = np.exp(1-self.G/(self.G+1-g))
            F = self.F0*2**lamda

            # 所有的解都要被变异一次
            # 确保选择的x1,x2,x3和当前被变异的解xn各不相同
            for n in range(self.NP):
                x1 = random.randint(0, self.D, 1)
                while x1 == n:
                    x1 = random.randint(0, self.D, 1)
                x2 = random.randint(0, self.D, 1)
                while x2 == n or x2 == x1:
                    x2 = random.randint(0, self.D, 1)
                x3 = random.randint(0, self.D, 1)
                while x3 == n or x3 == x1 or x3 ==x2:
                    x3 = random.randint(0, self.D, 1)

                # v接受变异的解空间
                v[n] = x[x1] + F*(x[x2] - x[x3])

            # 交叉操作
            '''扩展解空间:实际上应该是上一步作为扩展,因为交叉概率有可能低;'''
            r = random.randint(0,self.D,1)  # 生成[0,self.D)的随机整数,1:一个
            for d in range(self.D):
                p = random.rand()
                if p < self.Pc or d == r:
                    u[:,d] = v[:,d] # 满足交叉条件,u接收d维度上v的所有解
                else:
                    u[:,d] = x[:,d] # 否则接收d维度上x的所有解

            # 边界条件处理
            k = (u<self.Xx).sum() + (u>self.Xs).sum()
            while k > 0:
                if (u<self.Xx).sum() > 0:
                    u[u<self.Xx] = random.rand()*(self.Xs - self.Xx) + self.Xx
                elif (u>self.Xs).sum() > 0:
                    u[u > self.Xs] = random.rand() * (self.Xs - self.Xx) + self.Xx
                k = (u < self.Xx).sum() + (u > self.Xs).sum()

            # 选择操作
            yu = self.func(u.T)
            index1 = np.where(yu<y)
            x[index1] = u[index1]
            y = self.func(x.T)
            trace.append(min(y))
            # if min(y) < self.E:
            #     break
            g = g + 1


        yk = np.sort(y)
        index2 = np.argsort(y)
        xk = x[index2]
        bx = xk[0]
        by = yk[0]

        return trace,bx,by

    def drawer(self):
        y, bx,by = self.de()
        plt.rc('legend', fontsize=16)
        matplotlib.rcParams['font.family'] = 'Kaiti'
        fig = plt.figure(figsize=(10,5.5),dpi=100)
        plt.plot(y, 'b:d', markerfacecolor='red',markersize=3,linewidth=1.5, label='差分进化算法仿真实例')  # 1.线型颜色、线型风格、标记风格;2.线宽 3.标记颜色填充
        plt.xlabel('迭代次数', fontproperties='Kaiti', fontsize=14)  # 坐标轴标签设置
        plt.ylabel('适应度函数值', fontproperties='Kaiti', fontsize=14)
        plt.legend() # 添加图例
        # 图题
        plt.title(r'差分进化算法求解$Min:f(x)=\sum_{i=1}^{n} x_{i}^{2}\left(-20 \leqslant x_{i} \leqslant 20\right)$',
                  fontproperties='Kaiti', fontsize=14)
        plt.annotate('(最小值为:%.4f)'%by,xy=(len(y),by),xytext=(len(y)-40,70),fontproperties='Kaiti',fontsize=14,arrowprops=dict(facecolor='red',shrink=1.5,width=1.5,headwidth=5))
        plt.grid(True) # 网格
        plt.show()


da = DE(50,10,2000,0.4,0.1,20,-20,1e-6)
y,bx,by = da.de()
da.drawer()
print(by)

实验结果

  • 相较于遗传算法,差分进化过程就比较陡峭,不平滑。
    Alt
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值