打造最详细最简单的python遗传算法,每一行都有注释,有手就行论文实战。

#data:2022-10-27
#author:斜阳
#theme:遗传算法实例

import numpy as np
import math

##############################定义参数#################################
DNA_bit = 13 # 一个DNA的二进制位数,(第一维表示符号位),长度自己指定即可,越长精度越高
Int_bit = 2  # DNA_bit-1(符号位bit)之后整数占的bit位
DNA_num = 2  # DNA的个数
animal_num = 200 # 开始种群的数量,一个种群是一个解,包含一个x和一个y
cross_rate = 0.8 # 生殖交叉概率
variation_rate = 0.005  # 变异的概率
generator_n = 50 # 种群演变的次数
limit_area = [-3, 3] # 值域

######################################定义目标函数###################################
def f(x, y):
    return 3*(1-x)**2*np.exp(-(x**2)-(y+1)**2)- 10*(x/5 - x**3 - y**5)*np.exp(-x**2-y**2)- 1/3**np.exp(-(x+1)**2 - y**2)

#翻译DNA
def translate_DNA(animal):  # 解码种群的DNA
    def DNA2t10(DNA):#DNA二进制转换成十进制的x和y
        sum = 0
        # sign定义符号位,计算机中的符号位,就是在处理二进制数据时,专门规定有一位,

        sign = DNA[0] # 是用来确定数据的正负,符号位是1表示负数,是0表示正数,
        data = DNA[1:]# 去除符号位后面剩余的DNA,要转换成十进制
        if sign == 0:  # 符号位(表示二进制的正负)赋值,转换为二进制的正负号
            flag = -1#flag记录程序状态
        else:
            flag = 1
        #Int_bit  DNA_bit-1 x和y整数形式的位数
        for i in range(0, len(data)):#将data分成了0-int_bit-len(data)两部分
            if data[i] == 1:
                sum += math.pow(2, Int_bit - i - 1)
        # for i in range(Int_bit, len(data)):
        #     if data[i] == 1:
        #         sum += math.pow(2, Int_bit - i - 1)
        return flag * sum#正负号×十进制的数
    DNA_result = []
    for i in range(0, DNA_bit * DNA_num, DNA_bit):#步长为DNA_bit,0-26 两个整数
        DNA = animal[i:i + DNA_bit]#13个数为一截进行赋值
        translated_DNA = DNA2t10(DNA)#将13位的二进制数送进翻译函数中,转换成十进制
        DNA_result.append(translated_DNA)#结果包含x和y
    return DNA_result


#初始化种群************此处适合编写约束条件,根据自己要求进行编写*******************************
def flag_limit_area(animal, limit_area):  # 判断种群是否符合值域,否则一票否决
    x, y = translate_DNA(animal)#有一点多余,直接用x和y就可以
    if x <= limit_area[1] and x >= limit_area[0] and y <= limit_area[1] and y >= limit_area[0]:
        return True
    else:
        return False

#计算适应度
def get_fitness(animals):  # 计算种群各个部分的适应度
    fitness_score = np.zeros(len(animals))#生成初始的适应度分数,全为0
    fit_flag = np.zeros(len(animals))#生成适应度旗帜,判断是否在区间内
    for i in range(len(animals)):#len(animals)=200=种群的数量,遍历每一个种群
        x, y = translate_DNA(animals[i])#二进制转换成十进制
        fitness_score[i] = f(x, y)#根据目标函数计算适应度分数
        # if flag_limit_area(animals[i], limit_area):#判断x和y是否在区间内,返回true和false
        #     fit_flag[i] = 1#标记1,表示在区间内
        # else:
        #     fit_flag[i] = 0


    fitness_score = (fitness_score - np.min(fitness_score)) + 1e-5#把负数都成非负数,且接近于0
    # fitness_score = fitness_score * fit_flag # 如果不符合定义域就不取了,乘0就消失了,矩阵的乘法
    fitness_p = fitness_score / (fitness_score.sum())  # 计算被选择的概率,是长度200的数组
    return fitness_p

#适者生存
#numpy.random.choice(a, size=None, replace=True, p=None)
#从a(只要是ndarray都可以,但必须是一维的)中随机抽取数字,并组成指定大小(size)的数组
#replace:True表示可以取相同数字,False表示不可以取相同数字
#数组p:与数组a相对应,表示取数组a中每个元素的概率,默认为选取每个元素的概率相同。

#a = np.arange(3)
#一个参数 默认起点0,步长为1 输出:[0 1 2]

#选择操作
def select_animal(animals, fitness):  # 按照适应度选择留下的种群,选择适应度高的种群,重新组成200个种群
    idx = np.random.choice(np.arange(animal_num), size=animal_num, replace=True, p=(fitness)/(fitness.sum() + 1e-8))
    return animals[idx]#idx是长度为200的数组

#生殖变异
def variation(children, variation_rate):  # 模拟编译,输入一个种群
    if np.random.rand() < variation_rate:  # 以MUTATION_RATE的概率进行变异
        mutate_point = np.random.randint(0, DNA_bit * 2)  # 随机产生一个实数,作为变异点,代表要变异基因的位置
        children[mutate_point] = children[mutate_point] ^ 1  # 这一位取反,因为只有01,所以取相反的数
        # ^在算术运算中,表示异或。
        # 4^3就是相当于把4化为二进制为100,
        # 3化为二进制为11,
        # 现在二进制100异或011,
        # 异或运算中:1对1为0;1对0是1;0对1是1;0对0是0,所以100异或011就是1异或0为1,0异或1为1,0异或1为1。就是111,化为十进制2^2+2^1+1=7
    return children#输入多少数量,返回多少数量,返回一个种群

#生殖交叉变异
def crossover_and_variation(animals, cross_rate):  # 模拟生殖过程(包括交配和变异),输入200个种群
    new_animals = []
    for father in animals:#在200个种群中循环
        child = father  # 选择父亲,在种群中循环的下标,与子代child的下标同步
        if np.random.rand() < cross_rate:  # 每个种群产生子代时不是必然发生交叉,而是以一定的概率发生交叉
            mother = animals[np.random.randint(animal_num)]  # 再选择母亲,在200的数字中随机选择数字,作为下标
            cross_points = np.random.randint(low=0, high=DNA_bit * DNA_num)  # 随机产生交叉的点,在2-26中随机选择数字,作为DNA的交叉点
            child[cross_points:] = mother[cross_points:]  # 交叉互换,模拟生殖,从交叉点往后的片段都进行交换
        variation(child, variation_rate)  # 变异,当前的child进行变异,是一个种群
        new_animals.append(child)#child为长度200的数组
        #循环完200个种群,跳出循环
    return np.array(new_animals)#np.array转换成数组形式

#查看最终答案,打印出来就结束了
def get_result(animals):  # 获取结果,200个种群
    fitness = get_fitness(animals)#返回的是每个种群被选择的概率,长度200的数组
    max_fitness_index = np.argmax(fitness)#选择最大的选择概率的索引(下标)
    print("max_fitness:", fitness[max_fitness_index])
    x, y = translate_DNA(animals[max_fitness_index])
    print("最优的基因型:", animals[max_fitness_index])
    print("(x, y):", (x, y), f(x, y))
    return





# 初始化种群(即生成初始解),需要判断开始的种群是否符合值域
# DNA_bit = 13 # 一个DNA的二进制位数,(第一维表示符号位)
# Int_bit = 2  # DNA_bit-1(符号位bit)之后整数占的bit位
# DNA_num = 2  # DNA的个数,因为解是x和y
# animal_num = 200 # 开始种群的数量
# numpy.random.randint(low, high=None, size=None, dtype=int)

###########################运行程序的起点##################################
animals = np.random.randint(2,size=(animal_num, DNA_bit * DNA_num))#随机返回0-2的animal_num*【DNA_bit * DNA_num】的数组,
# 每个animal由两个DNA组成,每个DNA为DNA_bit位

#初始化合理的种群
num = animal_num#种群数量200
while (num):#循环直到种群数为0,检查所有的种群是否在要求区间,将种群调整为合理区间
    pos = num - 1#种群数量慢慢递减,pos是现在的种群数量
    if flag_limit_area(animals[pos], limit_area):#判断是否在要求区间
        num -= 1
    else:
        animals[pos] = np.random.randint(2, size=(1, DNA_bit * DNA_num))#重新生成新解

########################将符合要求的200种群按代数迭代,开始选择、交叉、变异######################################################

#生物遗传进化###################优化算法的部分#################################
# 模拟进化选择generator_n轮
for i in range(generator_n):#按着代数进行循环
    fitness_score = get_fitness(animals)  # 计算适应度,返回每一个种群被选择的概率,一个种群是一个解,输入200个种群
    #返回的是200长度的数组,往下输入进行【选择操作】
    selected_animals = select_animal(animals, fitness_score) # 根据适应度值,适者生存,选了200个
    #根据概率(适应度分数)选择了200个种群,往下进行交叉变异
    animals = crossover_and_variation(selected_animals, cross_rate)  # 生殖、变异,根据设置的代数重复计算,输入200个种群

###############完成选择、交叉、变异的操作###############################################################

#将选择、交叉、变异后的种群放入结果,此时已产生最优结果
get_result(animals)

基本上每一行代码都写了注释,慢慢看绝对容易理解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

酿豆腐超级好吃

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值