ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

python 简易版 遗传算法

2022-01-07 12:58:30  阅读:190  来源: 互联网

标签:code python self list rate 简易版 ga 遗传算法 gene


简易的遗传算法,使用时需要按照自己的需求修改fitness_func 函数

import random


def fitness_func(code):
    # code 为01字符串
    c_value = int(code, 2)

    return -(c_value - 1) * (c_value - 41) * (c_value - 480)


class GA(object):
    def __init__(self, fit_func, code_length=10, individual_number=100,
                 iterate_number=100, mutate_rate=0.001, elimination_rate=0.1, not_copy_rate=0.001,
                 nor_drop_rate=0.001):
        """

        :param fit_func: 适应度函数
        :param code_length: 基因长度
        :param individual_number: 种群个体数量
        :param iterate_number: 种群迭代次数
        :param mutate_rate: 变异概率
        :param elimination_rate: 种群淘汰率
        :param not_copy_rate: 最优个体不复制概率
        :param nor_drop_rate: 淘汰个体不淘汰概率
        """
        # 基因的长度
        self.ga_code_length = code_length - 1
        # 种群中个体数量
        self.individual_number = individual_number
        # 种群迭代次数
        self.iterate_number = iterate_number
        # 适应度函数
        self.ga_fit_func = fit_func
        # 基因库
        self.ga_lists = []
        # 初始化基因库
        self.random_gene()
        # 下一代的基因库
        self.next_gene_list = []
        # 最佳个体
        self.best_individual = None
        # 最佳个体的适应度值
        self.best_score = 0
        # 变异概率
        self.mutate_rate = mutate_rate
        # 淘汰概率
        self.elimination_rate = elimination_rate
        # 直接复制中不被复制的概率 模拟意外事故的发生
        self.not_copy_rate = not_copy_rate
        # 直接剔除中 不被剔除的概率 模拟意外保留非最优事件
        self.nor_drop_rate = nor_drop_rate
        # 检查参数是否设置在正常范围
        self.check_init_parameter()

    def check_init_parameter(self):
        assert 0 < self.not_copy_rate < 1, 'not_copy_rate 范围为(0,1)'
        assert 0 < self.nor_drop_rate < 1, 'nor_drop_rate 范围为(0,1)'
        assert 0 < self.mutate_rate < 1, 'mutate_rate(变异概率) 范围为(0,1)'
        assert 0 < self.elimination_rate < 1, 'elimination_rate(淘汰比例) 范围为(0,1)'

    # 随机生成基因库
    def random_gene(self):
        for ii in range(self.individual_number):
            code = random.randint(0, 2 ** self.ga_code_length) | 2 ** (self.ga_code_length + 1)
            code = bin(code)[-(self.ga_code_length + 1):]
            self.ga_lists.append(code)

    # 复制
    def ga_copy(self, code):
        if random.random() > self.not_copy_rate:
            self.next_gene_list.append(code)

    # 交叉
    def ga_cross(self, code_list):
        code_list_len = len(code_list)
        temp = code_list_len // 2
        if code_list_len % 2 != 0:
            # code_list 不为偶数 从code_list 中随机复制一条添加进去
            code_list.append(code_list[random.randint(0, code_list_len - 1)])
            temp += 1

        # 顺序交叉 保证每个基因均被交叉
        for ii in range(temp):
            a, b = self._cross_gene(code_list[ii], code_list[ii + temp])
            self.next_gene_list.append(a)
            self.next_gene_list.append(b)

        # 随机交叉 补充基因库 保证基因库总基因数量不变 避免奇数问题,多增加一组 后面通过切片剔除
        for _ in range((self.individual_number - len(self.next_gene_list)) // 2 + 1):
            a, b = self._cross_gene(code_list[random.randint(0, code_list_len - 1)],
                                    code_list[random.randint(0, code_list_len - 1)])
            self.next_gene_list.append(a)
            self.next_gene_list.append(b)

        # 切片剔除多余基因段
        self.next_gene_list = self.next_gene_list[:self.individual_number]

    # 基因段交叉函数
    def _cross_gene(self, code1, code2):
        r = random.randint(0, self.ga_code_length)
        code1_a, code1_b = code1[:r], code1[r:]
        code2_a, code2_b = code2[:r], code2[r:]
        return code1_a + code2_b, code2_a + code1_b

    # 变异
    def ga_mutate(self):
        if random.random() < self.mutate_rate:
            r_number = random.randint(0, self.individual_number - 1)
            r_gene_index = random.randint(0, self.ga_code_length - 1)
            self.next_gene_list[r_number] = self._mutate(self.next_gene_list[r_number], r_gene_index)

    @staticmethod
    def _mutate(code, index):
        cl = list(code)
        if cl[index] == '0':
            cl[index] = '1'
        else:
            cl[index] = '0'
        code = ''.join(cl)
        return code

    # 丢弃函数 这其中有概率不丢弃
    def drop(self, code):
        if random.random() < self.nor_drop_rate:
            self.next_gene_list.append(code)

    # 进化到下一代
    def ga_evolute(self):
        self.next_gene_list = []
        fitness_score = []
        for item in self.ga_lists:
            fitness_score.append(self.ga_fit_func(item))

        # 最大的适应度
        max_fs = max(fitness_score)
        # 最小的适应度
        min_fs = min(fitness_score)

        # 适应度大于该值 执行交叉操作 (适应度在10%之上)
        cross_score = self.elimination_rate * (max_fs - min_fs) + min_fs

        # 这里应该需要修改为轮盘赌的形式 还未修改
        cross_list = []
        for gene, fs in zip(self.ga_lists, fitness_score):
            # 保留最佳个体
            if fs == max_fs:
                self.ga_copy(gene)
                cross_list.append(gene)
            elif fs > cross_score:
                cross_list.append(gene)
            else:
                self.drop(gene)

        self.ga_cross(cross_list)
        self.ga_mutate()
        self.ga_lists = self.next_gene_list[:]
        self.next_gene_list = []

    def get_best(self):
        bs = self.ga_fit_func(self.ga_lists[0])
        bi = self.ga_lists[0]
        for item in self.ga_lists:
            if self.ga_fit_func(item) > bs:
                bs = self.ga_fit_func(item)
                bi = item

        # 最大的适应度
        self.best_score = bs
        self.best_individual = bi
        print('best_score=', bs)
        print('best_individual=', int(bi, 2))

    def fit(self):
        for _ in range(self.iterate_number):
            self.ga_evolute()


if __name__ == "__main__":
    ga = GA(fitness_func, iterate_number=1000)
    ga.fit()
    ga.get_best()

标签:code,python,self,list,rate,简易版,ga,遗传算法,gene
来源: https://blog.csdn.net/Wu123456CS/article/details/122361816

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有