遗传算法 - 函数最优解计算


任务描述

本关任务:使用 python 实现遗传算法,并求目标函数最优解。

相关知识

为了完成本关任务,你需要掌握:1.遗传算法,2.使用 python 实现遗传算法。

遗传算法

基因和染色体

在遗传算法中,我们首先需要将要解决的问题映射成一个数学问题,也就是所谓的数学建模,那么这个问题的一个可行解即被称为一条染色体或个体。如:

3x+4y+5z<100

[1,2,3],[2,3,4],[3,2,1]均为这个函数的可行解,这些可行解在遗传算法中均被称为染色体,每一个元素就被称为染色体上的一个基因。

染色体编码与解码

遗传算法的运算对象是表示染色体的符号串,所以必须把变量 x,y,z 编码为一种符号串。常见的编码方式如用无符号二进制整数来表示。解码即将二进制整数转换回最初的表现型。

编码: 5 --> 0101。 解码: 0101 --> 5

初始群体的产生

遗传算法是对群体进行的进化操作,需要给其准备一些表示起始搜索点的初始群体数据。假如群体规模的大小取为 4,即群体由 4 个染色体组成,每个染色体可通过随机方法产生。

如: 011101 , 101011 , 011100 , 111001。

物竞天择

  1. 适应度函数:遗传算法中以染色体适应度的大小来评定各个染色体的优劣程度,从而决定其遗传机会的大小。
  2. 选择函数:自然界中,越适应的个体就越有可能繁殖后代。但是也不能说适应度越高的就肯定后代越多,只能是从概率上来说更多。常用的选择方法有轮盘赌选择法。

若fi​表示每个染色体的适应度,则每个个体遗传下来的概率为:

p(i)=i∑​fi​fi​​

由公式可以看出,适应度越高,则遗传下来的概率就越大,好比赌轮盘,轮盘上所占面积越大,则被小球滚到的概率就越大。

交叉与变异

交叉是遗传算法中产生新的个体的主要操作过程,以一定的概率决定个体间是否进行交叉操作。

如上图为父辈染色体进过交叉后产生新的染色体的过程。

变异为另一种产生新个体的操作,它可以为种群带来多样性:

也就是将的染色体中的基因,随机的由0变成1,或1变成0

遗传算法流程

遗传算法流程:

  1. 初始化种群
  2. 计算适应度
  3. 选择适应度高的个体
  4. 通过交叉变异选择新的染色体
  5. 终止进化

使用python实现遗传算法。

本关任务是使用遗传算法求解目标函数最大值,首先需要随机产生很多个解,即初始化种群,代码如下:

  1. #初始化种群
  2. pop = np.random.randint(2, size=(POP_SIZE, DNA_SIZE)) # Size函数需要传入两个参数 POP_SIZE为解的个数,即染色体个数。DNA_SIZE为染色体长度

其中POP_SIZE为解的个数,即染色体个数。DNA_SIZE为染色体长度。

由于染色体为二进制编码,所以还需要将二进制转换为浮点数的解码方法:

  1. #解码
  2. def translateDNA(pop):
  3. return pop.dot(2 ** np.arange(DNA_SIZE)[::-1]) / float(2**DNA_SIZE-1) * X_BOUND[1]

上述代码中: pop.dot(2 ** np.arange(DNA_SIZE)[::-1])已经转换成十进制但是需要归一化到 0~5 ,如有 1111 这么长的 DNA,要产生的十进制数范围是 [0, 15] ,而所需范围是 [-1, 1] ,就将 [0,15] 缩放到 [-1,1] 这个范围。

a[::-1]相当于a[-1:-len(a)-1:-1],也就是从最后一个元素到第一个元素复制一遍。所以你看到一个倒序,np.arange(DNA_SIZE)[::-1]得到 10,9,8,...,0 。

如将 10101 转换到 0 到 5 之间:

x=25−124+22+2+0​×5

然后计算每个染色体的适应度,由于是求解最大值,函数值越大则越应该被选择,所以,将每个染色体对应的函数值减去最小值作为适应度:

  1. #获取染色体适应度
  2. def get_fitness(pred):
  3. return pred + 1e-3 - np.min(pred)

再选择适应度高的染色体:


#选择适应度高的染色体
def select(pop, fitness):
idx = np.random.choice(np.arange(POP_SIZE), size=POP_SIZE, replace=True,
p=fitness/fitness.sum())
return pop[idx]

再对染色体进行交叉变异操作:

  1. #交叉
    def crossover(parent, pop):
    if np.random.rand() < CROSS_RATE:
    i_ = np.random.randint(0, POP_SIZE, size=1)
    cross_points = np.random.randint(0, 2, size=DNA_SIZE).astype(np.bool)
    parent[cross_points] = pop[i_, cross_points]
    return parent
    #变异
    def mutate(child):
    for point in range(DNA_SIZE):
    if np.random.rand() < MUTATION_RATE:
    child[point] = 1 if child[point] == 0 else 0
    return child

总流程如下:

  1. 
    def F(x): return np.sin(10*x)*x + np.cos(2*x)*x
    
    def ga(F):
    '''
    F:需要求解的函数
    '''
    #初始化种群
    pop = np.random.randint(2, size=(POP_SIZE, DNA_SIZE))
    #开始进化
    for _ in range(N_GENERATIONS):
    #计算函数值
    F_values = F(translateDNA(pop))
    #计算适应度
    fitness = get_fitness(F_values)
    #选择适应度高的个体
    pop = select(pop, fitness)
    pop_copy = pop.copy()
    #通过交叉变异选择新的染色体
    for parent in pop:
    #交叉产生子代
    child = crossover(parent, pop_copy)
    #变异产生子代
    child = mutate(child)
    #子代代替父代
    parent[:] = child
    #获取最优解
    x = translateDNA(pop)[-1]
    return x

其中:

  1. N_GENERATIONS为进化轮数。
  2. CROSS_RATE为交叉概率。
  3. MUTATION_RATE 为变异概率。
  4. X_BOUND 为函数定义域。

编程要求

根据提示,在右侧编辑器的 begin-end 间补充代码,实现遗传算法。并求解函数f(x)在区间 [0,5] 上的最大值:

f(x)=xsin(10x)+xcos(2x)

函数图像如下:

测试说明

平台会调用你实现的方法,求解函数最优解,若你求得最优解与正确答案绝对值小于 0.1 则视为通关,否则输出你求得的最优解。


开始你的任务吧,祝你成功!

代码如下:

#encoding=utf8
import numpy as np
DNA_SIZE = 10   
POP_SIZE = 100         
CROSS_RATE = 0.8         
MUTATION_RATE = 0.003    
N_GENERATIONS = 500
X_BOUND = [0, 5] 
#获取染色体适应度
def get_fitness(pred): 
    return pred + 1e-3 - np.min(pred)
#解码
def translateDNA(pop): 
    return pop.dot(2 ** np.arange(DNA_SIZE)[::-1]) / float(2**DNA_SIZE-1) * X_BOUND[1]
#选择适应度高的染色体
def select(pop, fitness):    
    idx = np.random.choice(np.arange(POP_SIZE), size=POP_SIZE, replace=True,
                           p=fitness/fitness.sum())
    return pop[idx]
#交叉
def crossover(parent, pop):     
    if np.random.rand() < CROSS_RATE:
        i_ = np.random.randint(0, POP_SIZE, size=1)                             
        cross_points = np.random.randint(0, 2, size=DNA_SIZE).astype(np.bool)   
        parent[cross_points] = pop[i_, cross_points]                            
    return parent
#变异
def mutate(child):
    for point in range(DNA_SIZE):
        if np.random.rand() < MUTATION_RATE:
            child[point] = 1 if child[point] == 0 else 0
    return child
def ga(F):
    '''
    F:需要求解的函数
    x:最优解
    '''
    #********* Begin *********#
    #初始化种群
    pop = np.random.randint(2, size=(POP_SIZE, DNA_SIZE)) # Size函数需要传入两个参数 POP_SIZE为解的个数,即染色体个数。DNA_SIZE为染色体长度
    #********* End *********#
    #开始进化
    for _ in range(N_GENERATIONS):
        #计算函数值
        F_values = F(translateDNA(pop))
        #计算适应度
        fitness = get_fitness(F_values)
        #选择适应度高的个体
        pop = select(pop, fitness)
        pop_copy = pop.copy()
        #通过交叉变异选择新的染色体
        for parent in pop:
            #交叉产生子代
            child = crossover(parent, pop_copy)
            #变异产生子代
            child = mutate(child)
            #子代代替父代
            parent[:] = child
    #获取最优解
    x = translateDNA(pop)[-1]
    return x

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于Matlab遗传算法求解函数优化问题源码+代码注释+项目说明.zip 【资源介绍】 该项目是个人课程作业,答辩评审分达到95分,代码都经过调试测试,确保可以运行!欢迎下载使用,可用于小白学习、进阶。 该资源主要针对计算机、通信、人工智能、自动化等相关专业的学生、老师或从业者下载使用,亦可作为期末课程设计、课程大作业、毕业设计等。 项目整体具有较高的学习借鉴价值!基础能力强的可以在此基础上修改调整,以实现不同的功能。 ## 问题叙述 - 以函数优化为例,求f(x)=x*sin(10π*x)+1.0的最大值,其中x∈[-1,2]。 - 假设适应度函数为f(x),至于种群规模、选择算法、交叉概率、变异概率和计算精度等自行决定。 ## 问题分析 为了解决给定的优化问题,即通过遗传优化算法求解函数的最大值,则按照遗传算法的解题步骤进行。 1. 首先,需要确定种群规模,即初始解的数量,以及交叉概率和变异概率来保持种群的多样性。 2. 其次,选择合适的选择算法来确定优秀个体。 3. 最后,使用适应度函数f(x)对种群中的个体进行评估,并根据选择、交叉和变异操作生成下一代种群。 通过迭代该过程,并记录每一代中的最优解,最终可以得到函数f(x)在给定区间上的最大值。 ## 结果分析 - 在种群大小为100、编码长度为10、交叉概率为0.8、变异概率为0.05,迭代400次的条件下,程序运行结果和最优解如下: ![运行结果] ![最优解] - 根据运行结果,最优解为(1.85,2.84),符合根据图形观察获得的最大值大致位置,说明该遗传优化算法可以正确解出函数的最大值。 - 同时在迭代过程中可以清晰地观察到程序在不断向着最优解的方向接近,符合遗传算法的正确进行流程。 ## 总结 1. 实验的迭代过程中,程序不断朝着最优解的方向接近,符合遗传算法的正确流程。 2. 通过选择、交叉和变异等操作,优秀个体逐渐被筛选出来并逐步优化。 3. 通过观察种群适应度的变化趋势和每一代中最优解的收敛情况,有助于了解算法的性能和进化过程。
遗传算法是一种基于生物进化原理的搜索算法,它可以用于解决函数优化问题。Python是一种强大的编程语言,具有丰富的科学计算库,因此可以很方便地实现遗传算法函数最优解。 首先,我们需要定义适应度函数,该函数用于评估每个个体在问题域中的适应度。适应度函数可以根据具体的问题进行设计,常见的选择包括均方误差、目标函数值等。 然后,我们需要初始化种群,将种群中的个体表示成染色体的形式。对于函数优化问题,染色体可以表示为一串代表函数自变量取值的基因序列。 接下来,通过选择、交叉和变异等操作来进行种群的演化。选择操作根据个体的适应度进行选择,适应度高的个体被选中参与繁殖。交叉操作通过基因的交换形成新的个体。变异操作对个体的基因进行随机的变异,以增加种群的多样性。 在每一代演化中,我们根据适应度函数对种群进行评估,并选择适应度高的个体进行繁殖。繁殖过程中,通过交叉和变异操作生成新的个体替代旧的个体。这一过程持续进行,直到满足停止条件(如达到最大代数或达到足够接近最优解)。 最后,从最终的种群中选取适应度最高的个体作为函数最优解。通过解码个体的基因序列,我们可以得到函数自变量的取值,从而得到函数最优解。 在Python中,我们可以使用numpy等科学计算库来进行矩阵操作和随机数生成,使用matplotlib等库进行结果的可视化。同时,Python还提供了多线程和分布式计算等方法,可以加速遗传算法的求解过程。 总之,Python 的强大功能和丰富的科学计算库使得我们能够方便地实现遗传算法函数最优解

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值