[基因遗传算法]进阶之二:最优规划问题--多种编码方式+多变量

参考资料:
《遗传算法求解带约束优化问题(源码实现》
《有约束的遗传算法(Python代码实现)》
《遗传算法原理及其python实现》


同系列文章:
《[基因遗传算法]原理思想和python代码的结合理解之(一) :单变量》


解决的问题:线性规划最优解的问题. 可以应用在运筹学,优化问题, 最优传输理论的离散问题,深度学习中. 对于较简单的问题,应用广泛.
解决问题案例:
在这里插入图片描述

  • 目标函数:最小化. 如果求最大值,目标函数添加负号-
  • 不等式约束条件: 以小于号 ≤ \leq 为主.If ≥ \geq ,添加负号-,转化形态.
  • 自变量范围: 有两个自变量 x , y x,y x,y.分别具有自己的上下限,且好处是自变量的范围是连续的.

一、个体与种群

在这里插入图片描述

Fig.1 种群,个体,基因的关系

A. 个体的编码问题

在前一篇,我们采用了二进制编码的方式.其好处在于做交叉、变异的时候,代码写的非常舒服(便利).但同时其缺点明显.如果 x x x的定义域范围更广,要求精度更细.则其DNA的长度(存储单位)则会更长.因此对于个体编码有二进制编码、格雷编码、实数编码、符号编码。,具体可见:《万字字符长文带你了解遗传算法(有几个算例源码)》

不同的编码对应于不同的交叉和变异的代码书写思路.

B. 实数编码的交叉和变异的思路(单变量)

以上一篇的目标函数 y = 10 ⋅ s i n ( 5 x ) + 7 ⋅ c o s ( 4 x ) y=10 \cdot sin(5x)+7\cdot cos(4x) y=10sin(5x)+7cos(4x),定义域 x ∈ [ 0 , 5 ] x \in [0,5] x[0,5]为例.

NP=5
pop=np.random.uniform(0, 5,(NP,))# 实数编码
pop 

结果:
array([4.10882862, 4.50177413, 1.63557154, 3.38813064, 2.84975806])
交叉的某种方式: 节选父与母的一部分.

def crossover(parent1,parent2):
    if np.random.rand() < PC:    #交叉概率
        gamma=round(np.random.rand(),2)#随机产生一个(0,1)浮点数,并保留2位小数
        parent1=gamma*parent1+(1-gamma)*parent2
    return parent1

变异的某种方式:重新实数赋值

def mutation(child):
    # 用随机赋值的方式进行变异
    if np.random.rand() < PM:#变异概率
        child= np.random.uniform(0,5)#重新随机赋值
    return child

种群的交叉和变异:

pop_copy=pop.copy()
for i in range(NP):
    #parent1=pop[i]
    parent2=pop_copy[np.random.randint(NP)]# 随机产生父母2
    child=crossover(pop[i],parent2)#交叉
    pop[i]=mutation(child) #变异
pop 

结果:
array([3.63316795, 4.50177413, 1.63557154, 3.38813064, 3.78147027])

二、多变量的问题

以目标函数 Z = 2 a + x 2 − a c o s 2 π x + y 2 − a c o s 2 π y Z=2a+x^2-acos2πx+y^2-acos2πy Z=2a+x2acos2πx+y2acos2πy求最小值为例. x ∈ [ − 5 , 5 ] , y ∈ [ − 5 , 5 ] , a = 10 x \in [-5,5], y\in [-5,5],a=10 x[5,5],y[5,5],a=10.
当多变量的时候,相当于个体具有多条染色体,对应的染色体(表示相同特征,或说对应同一个自变量)之间才能交叉.

A.多变量的目标函数书写

def fitness_func(X):
    # 目标函数,即适应度值,X是种群的表现型
    a = 10
    pi = np.pi
    x = X[:, 0]
    y = X[:, 1]
    return 2 * a + x ** 2 - a * np.cos(2 * pi * x) + y ** 2 - a * np.cos(2 * 3.14 * y)

B. 二进制的编码的交叉和变异思路(多变量)

NP=5 #种群数量
DNA_SIZE=4#DNA长度,应设为20,为方便看结果缩小的
DNA_NUM=2#染色体个数
pop= np.random.randint(0, 2, (NP, DNA_SIZE*DNA_NUM))  
# 随机初始化种群,为50*40的0-1矩阵
pop 

结果:
在这里插入图片描述
解码方式

  • 对单条染色体解码
def decode(x, a, b):
    """解码,即基因型到表现型,同单变量相同"""
    xt = 0
    for i in range(len(x)):
        xt = xt + x[i] * np.power(2, i)
    return a + xt * (b - a) / (np.power(2, len(x)) - 1)
# 或者
def decode(x, a, b):
    """解码,即基因型到表现型"""
    DNA_SIZE=len(x)
    x_d=x.dot(2 ** np.arange(DNA_SIZE)[::-1]) *(b-a)/ float(2**DNA_SIZE-1) +a
    return x_d
  • 对个体(多条染色体)解码
def decode_X(pop: np.array,lb,ub):
    """
    对整个种群的基因解码,上面的decode是对某个染色体的某个变量进行解码
    pop:种群(二进制基因)
    lb: 变量的下限列表
    ub: 变量的上限列表
    """
    X =np.zeros((NP,n_dim))#解码后的种群的变量值存储,(5,2)
    indivi=np.zeros(n_dim)
    for i in range(NP):
        for j in range(n_dim):
            x =decode(pop[i,DNA_SIZE*j:DNA_SIZE*(j+1)],lb[j],ub[j])
            #xi = decode(pop[i, :20], -5, 5)
            indivi[j]=x
        
        X[i, :] = indivi
    return X

解码计算:

NP=5
DNA_SIZE=20#设为20
n_dim=2
pop= np.random.randint(0, 2, (NP, DNA_SIZE*n_dim)) 
lb=[-5,-5]
ub=[5,5]
X = decode_X(pop,lb,ub)
X

结果为:
array([[ 2.06021982, -0.35688911],
[ 2.00679494, -3.61610281],
[-4.44379753, -4.92298119],
[ 4.34191641, 4.12501252],
[-4.70489474, -0.42363684]])
(多变量)交叉与变异
与(单变量)二进制的交叉与变异类似,只是在外面多加了一套染色体个数的循环.

C.使用sko.GA解决问题

def aim(p):
    a = 10
    pi = np.pi
    x,y=p
    return 2 * a + x ** 2 - a * np.cos(2 * pi * x) + y ** 2 - a * np.cos(2 * 3.14 * y)
ga = GA(func=aim, n_dim=2, size_pop=50, max_iter=1000, 
lb=[-5,-5], ub=[5,5], precision=1e-7) 
best_result= ga.run()
print(best_result)

out:
(array([-9.94958624e-01, -3.72529039e-08]), array([0.99495906]))

总结思考: 通过这两篇的手写代码,可以充分理解基因遗传算法与代码结合的思想.
然而,我们与第三方库比较发现.第三方库sko.GA更好用.几行代码就解决了.因此,接下来思考,如何用sko.GA解决实际问题.

  • 2
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值