DE差分进化算法--Python代码详解

差分进化算法

算法思路:

1.算法流程图:差分进化算法流程图

2.算法思想:

①确定目标函数    例如求f(x)=x^2+x/2+x^2/3函数的最小值,x的取值范围为(-20,+20)
②初始化一些初始解    也就是先**随机**生成一些x
③求初始解的适应度值    也就是将随机生成的解带入到函数中去求出函数值
④选择适应度最好的解    选择出上述操作之后函数值最好的n(n靠自己定义)个解(也就是x)
⑤对上述选择的解进行交叉、变异操作(这两个操作下面细讲)
⑥对交叉、变异后的新解进行边界处理    因为我们x已经定义了取值范围,x不能超出此范围取值
⑦重新求出经过操作后的解的适应度    也就是求出新解的函数值
⑧判断是否已经满足结束条件,否则返回第四步

3.算法重要参数

①种群大小P(population)    也就是随机生成解的个数
②个体维度D(dimension)    也就是随机生成解的维度大小(维度指的是很可能x并不是单指一个实数,有可能是指一个矢量,也有可能指的是矩阵中的一行或一列)
③变异算子CR1    进行变异操作时需要的参数
④交叉算子CR2    进行交叉操作时需要的参数
⑤迭代次数G(generation)    一共需要循环的次数

变异交叉操作详解

变异:生物学意义上也就是进行基因变异,在该算法中相当于改变个体中的某些部分。例如初始x=[1,2,3,4,5,6]为一个6维,经过变异操作后可能变成[1,21,3,4,56,65]

交叉:生物学上叫做基因交叉,在该算法中相当于两个多维度的个体相互交换某些维度的数值。例如x1=[1,9,8,7,12]  x2=[98,54,63,21,1]对x1、x2进行1、3、5维度的交叉,得出一个新的x1`=[98,9,63,7,1],x2`=[1,54,8,21,12]

变异以及交叉操作技术后得出新的个体,然后带入到操作流程中

代码示例(详细注解)

导入代码所需要的库

import random
import numpy as np
import matplotlib.pyplot as plt   
plt.rc('font',family='KaiTi')  #中文显示问题

定义目标函数(也就是适应度函数)

def f1(x):
    return np.sum((x - 1) **2 )#求(x-1)的平方的最小值

初始化算法所需要参数

population_size = 100  #定义种群规模,也就是一共有多少个个体

dimension = 20  #定义个体维度

#定义个体边界值

lower_band = -100

upper_band = 100

F = random.uniform(0.2,0.8)  #随机生成一个实数来作为差分权重

CR1 = 0.2  #定义交叉概率

CR2 = 0.2  #定义变异因子

generations = 100
#初始化种群

population = np.random.uniform(lower_band,upper_band,(population_size,dimension))
#查看population种群

population
array([[ 61.08988255,  93.58656325,  25.10739419, ..., -90.79082588,
        -17.43888371,  64.42807136],
       [ 26.85052576,  94.50131987,  58.80338945, ..., -24.7227089 ,
        -46.12172234, -84.25432156],
       [-92.78709384, -37.43311139, -17.98510195, ...,  -7.85818691,
         95.31387058, -77.89638401],
       ...,
       [ 68.33198157,  -2.60425885, -24.06922746, ..., -53.12641888,
         19.23669603, -14.28417421],
       [  3.50878467, -19.40844065, -76.05249883, ...,   9.11712924,
         19.42098486,  58.17541794],
       [-59.37100122,  -1.68449545, -33.68313521, ...,  97.61324629,
        -71.12427809,  41.07406765]])
#计算每个个体的适应度值,就是上文所说的求出每个个体的函数值(两种方法)

#①利用省略缩写
fitness1 = np.array([f1(ind) for ind in population])

#②不省略
list_fitness = []
for ind in population :
    list_fitness.append(f1(ind))
fitness2 = np.array(list_fitness)

#两种方法结果是一样的
#查看两种方法得出结果是否不同
fitness1==fitness2
array([ True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True,
        True])

差分进化算法过程

#定义两个列表
best_fitness_history = []  #用来储存最佳适应度值
best_solution_history = []  #用来存储最优解

#两层循环
for generation in range(generations):  #外层循环用来判断是否超出定义迭代次数
    new_population = np.copy(population)   #复制一份population,对复制的种群进行以后的操作
    for i in range(population_size):   #内层循环用来判断超出种群范围以及提取种群信息
        indices = list(range(population_size))   #定义一个大小和种群规模一样的列表,用于下面操作数据提取
        indices.remove(i)    #indices依次移除某位置的数据,用于记录此时的数据
        a,b,c = population[np.random.choice(indices,3,replace = False)]   #随机选择三个种群中的个体
        
        #变异操作
        mutant = a + F * ( b - c )    #对选择的三个个体进行变异操作
        
        #交叉操作
        crossover = np.random.rand(dimension) < CR1     #随机生成一个实数小于个体维度数,判断该实数是否小于交叉因子
        trial = np.where(crossover,mutant,population[i])  #np.where(condition,x,y) 当where内有三个参数时,第一个参数表示条件,当条件成立时where方法返回x,当条件不成立时where返回y
        
        #选择操作
        trial_fitness = f1(trial)   #对上面生成的新个体进行适应的求值,然后放入一个新的列表中
        if trial_fitness < fitness1[i]:  #如果新计算的个体适应度比原本个体的适应度好,选择新的个体以及新的适应度替换之前旧的数据
            new_population[i] = trial   #对副本中的数据进行替换,不影响原本的数据
            fitness1[i] = trial_fitness
            
    population = new_population    #将新生成的种群替换旧的种群
    best_fitness = np.min(fitness1)    #找到一代中适应度列表中最好的适应度
    best_solution = population[np.argmin(fitness1)]     #找出一代中最好适应度对应的个体

    best_fitness_history.append(best_fitness)   #将一代中最好的适应度储存
    best_solution_history.append(best_solution)  #将一代中最好的个体储存
    
    # 输出每一代的最优解和最优适应度
    # print(f"Generation {generation + 1}:\n Best Solution = {best_solution}, \nBest Fitness = {best_fitness}")

对计算出来的数据进行绘图

# 绘制适应度值随代数变化的曲线
plt.plot(best_fitness_history,c = 'blue',label = '迭代')
plt.legend(fontsize = 12)  #标明每条线的详细信息
plt.title('F1')
plt.xlabel('迭代次数')
plt.ylabel('最佳适应度')
plt.grid(True)
plt.show()

DE

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值