遗传算法的python实现

本文章提供了一个基本遗传算法,以求解函数:

                ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        f(x_{1},x_{2},x_{3},x_{4})=\frac{1}{x_{1}^2+x_{2}^2+x_{3}^2+x_{4}^2+1}

其中  -5\leqslant x_{1},x_{2},x_{3},x_{4}\leqslant 5,求解该函数的最大值来解释遗传算法。

遗传算法流程:

Step1. 初始化规模为N的种群,以及每个个体的染色体数目M,采用随机数生成每个个体的所有染色体;

Step2. 采用评估函数,对种群中的所有个体的所有染色体计算其适应值,并得到所有个体中染色体组的最佳适应值;

Step3. 采用轮盘赌选择算法对群体的染色体进行选择操作,产生规模同样为N的种群;

Step4. 按照概率Pc,从种群中选择染色体进行交配。每两个进行交配的父代染色体,交换部分基因,产生两个新的子代染色体,子代染色体取代父代染色体进入新种群。没有进行交配的染色体直接复制进入新种群;

Step5. 按照概率Pm,对新种群中染色体的基因进行变异操作。发生变异的基因数值发生改变。变异后的染色体取代原有染色体进入新群体,未发生变异的染色体直接进入新群体;

Step6. 变异后的新群体取代原有群体,重新计算群体中各个染色体的适应值。倘若群体的最大适应值大于Best的适应值,则以该最大适应值对应的染色体替代Best;

Step7. 当前进化代数Generation加1。如果Generation超过规定的最大进化代数或Best达到规定的误差要求,算法结束;否则返回Step3。

完整代码:

import random
import numpy as np

# 以求一个函数最大值为例,使用遗传算法进行问题求解
# 目标函数,其中x1,x2,x3,x4的取值范围[-5, 5]
def goal_function(x1, x2, x3, x4):
    return 1 / (x1**2 + x2**2 + x3**2 + x4**2 + 1)

class SGA:
    def __init__(self, group_size, chrom_num):
        self.group_size = group_size    # 群体规模
        self.chrom_num = chrom_num      # 染色体数目
        self.best = np.zeros(self.chrom_num)
        self.generation = 0             # 遗传代数
        self.best_value = 0

    def initialize(self):
        group = np.random.uniform(low=-5, high=5, size=(self.group_size, self.chrom_num))
        return group

    def evaluate(self, group):
        self.eval = np.zeros(self.group_size)
        max_adaption = 0
        idx = 0
        print("群体中个体适应值为:")
        for i in range(self.group_size):
            self.eval[i] = goal_function(group[i][0],group[i][1],group[i][2],group[i][3])
            if self.eval[i] > max_adaption:
                max_adaption = self.eval[i]
                idx = i
            print(f"{i+1}号个体的染色体为:{group[i]}, 适应值为:{self.eval[i]}")
        if max_adaption > self.best_value:
            self.best = group[idx]
            self.best_value = max_adaption
        print(f"{idx+1}号个体适应值最大为:{max_adaption}\n")

    # 采用轮盘赌算法进行选择
    def selection(self, group):
        print("轮盘赌算法选择个体进行交配")
        total = np.sum(self.eval)
        possibility = self.eval / total
        new_group = np.zeros([self.group_size, self.chrom_num])
        for i in range(self.group_size):
            r = np.random.random()
            idx = 0
            total_poss = possibility[idx]
            while r > total_poss:
                idx = idx + 1
                total_poss = total_poss + possibility[idx]
            new_group[i] = group[idx]
            print(f"第{i+1}次生成的随机数为:{r},根据轮盘赌选中的个体为:{idx+1}号染色体为:{group[idx]}")
        return new_group

    def crossover(self, group):
        new_group = self.selection(group)
        Pc = np.random.uniform(0.4, 0.99)
        crossover_select = []
        crossover = []
        generation = np.zeros([self.group_size, self.chrom_num])

        for i in range(self.group_size):
            r = np.random.random()
            if r > Pc:
                crossover_select.append(new_group[i])
            else:
                crossover.append(new_group[i])

        if len(crossover_select) <= 1:
            print(f"选择交配的样本数量为:{len(crossover_select)},选择样本数量不足,拒绝交配\n")
            for i in range(self.group_size):
                generation[i] = group[i]
                print(f"后代中{i + 1}号的染色体为:{generation[i]}")
            return generation

        print(f"选择交配的样本数量为:{len(crossover_select)},选择样本数量充足,开始交配")
        while len(crossover_select) > 1:
            # 选择交配样本
            father_idx = np.random.choice(len(crossover_select))
            father = crossover_select[father_idx]
            crossover_select.pop(father_idx)

            mother_idx = np.random.choice(len(crossover_select))
            mother = crossover_select[mother_idx]
            crossover_select.pop(mother_idx)

            models = ['single', 'mult', 'uniform']
            pattern = random.choice(models)
            print(f"选择父本为:{father},选择母本为:{mother},交配模式为:{pattern}")

            if pattern == 'single':
                chrom_idx = random.sample(range(self.chrom_num), 1)
                temp = father[chrom_idx]
                father[chrom_idx] = mother[chrom_idx]
                mother[chrom_idx] = temp

            if pattern == 'mult':
                num = random.randint(1, self.chrom_num)
                chrom_idxs = random.sample(range(self.chrom_num), num)
                for chrom_idx in chrom_idxs:
                    temp = father[chrom_idx]
                    father[chrom_idx] = mother[chrom_idx]
                    mother[chrom_idx] = temp

            if pattern == 'uniform':
                for i in range(self.chrom_num):
                    p = random.choice([0, 1])
                    if p == 1:
                        temp = father[i]
                        father[i] = mother[i]
                        mother[i] = temp

            crossover.append(father)
            crossover.append(mother)

        if len(crossover_select) == 1:
            crossover.append(crossover_select[0])

        for i in range(len(crossover)):
            generation[i] = crossover[i]
            print(f"后代中{i+1}号的染色体为:{generation[i]}")
        print("交配完成\n")


        return generation

    def variation(self, group):
        print("开始变异")
        Pm = np.random.uniform(0.7, 0.99)
        for i in range(self.group_size):
            for j in range(self.chrom_num):
                p = random.random()
                if p > Pm:
                    group[i][j] = random.random()
        print("变异完成\n")
        return group

    def train(self, iter_num=50):
        generation = self.initialize()
        for iter in range(iter_num):
            print(f"-------------------------------开始第{iter+1}训练----------------------------------------------")
            self.evaluate(generation)
            generation = self.crossover(generation)
            generation = self.variation(generation)
            self.evaluate(generation)
            print(f"当前迭代次数为:第{iter+1}次,得到的最大值为:{self.best_value},对应的个体为:{self.best}")

if __name__ == '__main__':
    np.set_printoptions(suppress=True, precision=9)
    sga =SGA(5, 4)
    sga.train(iter_num=150)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

火锅店的保安长

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

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

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

打赏作者

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

抵扣说明:

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

余额充值