python 简易版 遗传算法

简易的遗传算法,使用时需要按照自己的需求修改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()

上一篇:C语言利率


下一篇:js根据值的正负显示不同颜色