遗传算法求解函数最大值的python实现

已知函数y=f(x1,x2)=1/(x1^2 + x2^2+1),其中-5<=x1,x2<=5,用遗传算法求解y的最大值。

代码

import random
import numpy as np
import copy

max_value = 5 # 区间最大值
min = -5 # 区间最小值
len = max_value - min # 区间长度
chro = 6 # 染色体条数
G = 500 # 最大遗传代数
Pc = 0.8 # 交叉概率
Pm = 0.1 # 变异概率

# 求编码长度
def len_code(l):
    i = 0
    while True:
        if 2**(i-1) < l*10**4 < 2**i-1:
            # 由于需要表示x1和x2,因此返回长度应该是所求长度的两倍
            return 2*i
        i += 1

# 解码
def decode(x , len_area , len_code ,  min):
    left = x[:len_code] # 将左半部分取出来作为x1
    # 由于得到的left是列表,为了进行后续的进制转转,需要将其先转换为字符串
    x1_str = ''.join(left)
    x1_dec=int(x1_str, 2) # 将二进制转转为十进制
    right = x[len_code:] # 将右半部分取出来作为x1
    # 由于得到的right是列表,为了进行后续的进制转转,需要将其先转换为字符串
    x2_str = ''.join(right)
    x2_dec = int(x2_str , 2) # 将二进制转转为十进制
    x1 = min + x1_dec*len_area/(2**len_code-1)
    x2 = min + x2_dec*len_area/(2**len_code-1)
    return x1 , x2

# 计算适应度函数值
def f_value(population , L):
    # value由于存放每一组染色体的适应度函数值
    value = []
    # 遍历初始种群,计算每一个个体的适应度函数值
    for item in population:
        new_item = []
        for e in item:
            # 为了后续计算的方便,将每一个个体的0,1转换为字符形式
            new_e=str(e)
            new_item.append(new_e)
        # 计算x1,x2的值
        x1, x2 = decode(new_item, len, int(L / 2), min)
        # 计算个体适应度函数值,并将其追加到value列表中
        fit = round(1/(x1**2 + x2**2 + 1) , 4)
        value.append(fit)
    return value

# 计算被选择的概率和累积概率
def prob(v):
    prob_slect = [] # 初始化被选择概率
    prob_accum = [0]*chro # 初始化累积概率
    total = sum(v) # 求当前种群适应度的和
    for i in range(chro):
        # 被选择概率为个体的适应度值比上种群适应度和
        prob_slect.append(round(v[i] / total , 4))
        # 累积概率为当前个体之前的适应度值之和
        prob_accum[i] = round(sum(prob_slect) , 4)
    return prob_accum

# 轮盘赌选择
def roulette(former , probility):

    selection = [0]*chro
    for i in range(chro):
        random_num = round(random.random() , 4)
        for j in range(chro):
            if random_num < probility[0]:
                selection[i] = 0
            elif probility[j] < random_num < probility[j+1]:
                selection[i] = j+1
    # print(selection)
    select = []
    for e in selection:
        select.append(former[e])
    return select

# 单点交叉
def cross(chromosome , L):
    # print('1:',chromosome)
    # 定义新的列表用于存放交叉后的染色体
    chromosome_copy = copy.deepcopy(chromosome)
    new_chromosome = chromosome_copy.copy()
    i = 0
    while i < chro:
        # 产生chro/2个0到1之间的随机小数作为作为是否交叉的依据,并保留小数点后四位
        random_num = (round(random.random() , 4))
        # 产生L个随机整数作为作为交叉位置
        random_location = random.randint(0,L)
        # print('num:',random_num)
        # print('loc:',random_location)
        # 当随机数小于交叉概率时,进行交叉
        if random_num < Pc:
            # 交叉操作
            new_chromosome[i][random_location:] = chromosome_copy[i+1][random_location:]
            # 将经过交叉操作的染色体放入新染色体列表中
            new_chromosome[i+1][random_location:] = chromosome_copy[i][random_location:]
        i += 2
    return new_chromosome

# 单点变异
def variation(chromosome , L):
    # 产生一个chro*L大小的0到1之间的随机小数矩阵
    random_var = np.random.random((chro , L))
    # print(random_var)
    for i in range(chro):
        for j in range(L):
            # 当随机数小于变异概率时,进行变异
            if random_var[i][j] < Pm:
                # print(i,j)
                # 由于变异操作就是0,1的互换,因此可把当前数减一,再取绝对值来表示此操作
                chromosome[i][j] = abs(chromosome[i][j] - 1)
    return chromosome

# 主函数
def main():
    L = len_code(len)  # 编码长度
    # 随机初始化种群
    initial = np.random.randint(0, 2, (chro, L))
    # print(initial)
    i = 0
    while i < G:
        # print(i)
        # 计算种群适应度函数值
        if i == 0:
            value = f_value(initial.copy() , L)
        else:
            value = f_value(var_gene.copy() , L)
        # print(value)
        # 计算种群累积概率
        accumulate = prob(value)
        # print(accumulate)
        # 进行轮盘赌选择
        if i == 0:
            sel_gene = roulette(initial.copy() , accumulate)
        else:
            sel_gene = roulette(var_gene.copy() , accumulate)
        # 单点交叉
        cross_gene = cross(sel_gene.copy() , L)
        # 单点变异
        var_gene = variation(cross_gene.copy() , L)
        var_value = f_value(var_gene.copy() , L)
        if max(var_value) < max(value):
            var_gene = sel_gene
        i += 1
    final_value = f_value(var_gene.copy() , L)
    print("用遗传算法求得该函数的最大值为:" , max(final_value))

if __name__ == '__main__':
    main()

运行结果

图片:
遗传算法求解函数最大值的python实现_第1张图片
最近比较忙,之后有时间会详细介绍遗传算法及该代码,代码全为自己编写,注释详细,个人认为理解起来容易,望大家支持,有不懂或觉得代码有问题的地方可在评论区指出~

你可能感兴趣的