遗传算法 Python实现

  大家好,我叫亓官劼(qí guān jié ),在CSDN中记录学习的点滴历程,时光荏苒,未来可期,加油~博客地址为:亓官劼的博客

本文原创为亓官劼,请大家支持原创,部分平台一直在盗取博主的文章!!!

博主目前仅在CSDN中写博客,唯一博客更新的地址为:亓官劼的博客


在这里插入图片描述


本文中的遗传算法是之前所写,为10个种群,10个染色体的遗传算法实现。
适应值函数为di的累加
其余各项在代码中有注释,有需要的话可以自行查看,仅为遗传算法实现的一个示例。


import pandas as pd
import numpy as np
from pandas import DataFrame
import math, random
from math import log


# 种群类
class Population:
    def restraint(self,indvs):
        sum = 0
        for item in indvs:
            sum += self.data_list[item][4]
        if sum < 500:
            return True
        else:
            return False

    def __init__(self, data_file, size, cp, mp, gen_max):
        # data_file数据文件路径
        # size 为种群所包含的个体数
        # cp 个体之间的交叉概率
        # mp 个体之间的变异概率
        # gen_max 种群进化的最大世代数

        # data为读取的数据文件内容
        self.data = pd.read_excel(data_file, index_col=None)
        # 数据集个体约束
        self.data = self.data[(self.data['a_cp'] > 1) & (self.data['b_cp'] > 1) & (self.data['c_cp'] > 1)]
        self.cols = ['TARGET_FID', 'a', 'b', 'c', 'd', 'a_cp', 'b_cp', 'c_cp', 'd_cp']
        self.data_num = self.data.count()[0]  # 数据项数
        self.data_array = np.array(self.data)
        self.data_list = self.data_array.tolist()
        self.dir = {'TARGET_FID': 0, 'a': 1, 'b': 2, 'c': 3, 'd': 4, 'a_cp': 5, 'b_cp': 6, 'c_cp': 7, 'd_cp': 8}

        self.individuals = []  # 个体集合
        self.fitness = []  # 个体适应度集
        self.selector_probability = []  # 个体选择概率集合
        self.new_individuals = []  # 新一代个体集合
        self.elitist = {'chromosome': [0 for i in range(10)], 'fitness': 0, 'age': 0}  # 最佳个体的信息
        self.size = size  # 种群所包含的个体数
        self.chromosome_size = int(log(self.data_num, 2)) + 1  # 个体的染色体长度
        self.crossover_probability = cp  # 个体之间的交叉概率
        self.mutation_probability = mp  # 个体之间的变异概率
        self.generation_max = gen_max  # 种群进化的最大世代数
        self.age = 0  # 种群当前所处世代

        # 随机产生初始个体集,并将新一代个体、适应度、选择概率等集合以 0 值进行初始化
        v = self.data_num
        for i in range(self.size):
            # 这里直接使用了十进制,一般使用二进制来表示基因型
            indvs = [random.randrange(0, v) for i in range(10)]
            while self.restraint(indvs) is True:
                indvs = [random.randrange(0, v) for i in range(10)]
            self.individuals.append(indvs)
            self.fitness.append(0)
            self.selector_probability.append(0)

    # 适应度函数
    def Fitness(self, individual):
        # 适应值函数
        # individual 为个体
        f = 0
        for i in individual:
            f = f + self.data_list[i][2]
        return f

    # 计算个体适应度
    def compute_fitness(self):
        for i in range(self.size):
            self.fitness[i] = self.Fitness(self.individuals[i])

    # 计算个体复制概率
    def compute_select(self):
        sum = 0
        for i in range(self.size):
            sum += self.fitness[i]
        for i in range(self.size):
            self.selector_probability[i] = self.fitness[i] / sum

    # 复制
    def select(self):
        copy_num = 0
        for i in range(self.size):
            if self.selector_probability[i] * self.size > 1:
                copy_item = int(self.selector_probability[i] * self.size)
                self.selector_probability[i] -= copy_item
                for m in range(copy_item):
                    self.new_individuals.append(self.individuals[i])
        new_indvs_num = self.new_individuals.__len__()
        for i in range(self.size - new_indvs_num):
            # 当前最大复制概率的下标
            now_max_sp_index = self.selector_probability.index(max(self.selector_probability))
            self.selector_probability[now_max_sp_index] -= 1 / self.size
            self.new_individuals.append(self.individuals[now_max_sp_index])

    # 交叉
    def cross(self):
        # 随机筛选交叉个体
        # 这里个体是多染色体的,可以个体间交叉,也可以个体内交叉
        # 这里为个体内交叉

        cross_index = []
        for i in range(self.size):
            p = random.random()
            if p > (1 - self.crossover_probability):
                cross_index.append(i)
        cross_num = cross_index.__len__()
        # 下面开始选择交叉位置,由于这里的数据项为均不为2次幂的整数,为了保证数据安全,二进制位第一位默认不选。
        # 在选中交叉个体后,进行交叉
        for i in range(cross_index.__len__()):
            idvs = cross_index[i]
            item_1_index = random.randint(0, 10)
            item_2_index = random.randint(0, 10)
            item_1 = self.new_individuals[idvs][item_1_index]
            item_2 = self.new_individuals[idvs][item_2_index]
            # 由于我们个体中使用的十进制,首先要转化为2进制进行处理
            bin_item_1 = str(bin(item_1))[2:].zfill(self.chromosome_size)
            bin_item_2 = str(bin(item_2))[2:].zfill(self.chromosome_size)
            cross_position = random.randint(1, self.chromosome_size)
            new_bin_item_1 = bin_item_1[0:cross_position] + bin_item_2[cross_position:]
            new_bin_item_2 = bin_item_2[0:cross_position] + bin_item_1[cross_position:]
            new_item_1 = int(new_bin_item_1, 2)
            new_item_2 = int(new_bin_item_2, 2)
            self.new_individuals[idvs][item_1_index] = new_item_1
            self.new_individuals[idvs][item_2_index] = new_item_2
            if self.restraint(self.new_individuals[idvs]) is False:
                self.new_individuals[idvs] = self.individuals[idvs]

    # 变异操作
    def mutate(self):
        # 随机选择变异个体
        mutate_index = []
        for i in range(self.size):
            p = random.random()
            if p > (1 - self.mutation_probability):
                mutate_index.append(i)
        mutate_num = mutate_index.__len__()
        for i in range(mutate_index.__len__()):
            idvs = mutate_index[i]
            # 个体中随机一个染色体进行变异
            item = random.randint(0, 9)
            mutate_position = random.randint(1, self.chromosome_size - 1)
            item_bin = bin(self.new_individuals[idvs][item])[2:].zfill(self.chromosome_size)
            if item_bin[mutate_position] == '0':
                item_bin = item_bin[:mutate_position] + '1' + item_bin[mutate_position + 1:]
            else:
                item_bin = item_bin[:mutate_position] + '0' + item_bin[mutate_position + 1:]
            new_item = int(item_bin, 2)
            self.new_individuals[idvs][item] = new_item
            if self.restraint(self.new_individuals[idvs]) is False:
                self.new_individuals[idvs] = self.individuals[idvs]

    # 保留最佳个体
    def reproduct_elitist(self):
        # 与当前种群进行适应度比较,更新最佳个体
        j = -1
        for i in range(self.size):
            if self.elitist['fitness'] < self.fitness[i]:
                j = i
                self.elitist['fitness'] = self.fitness[i]
        if (j >= 0):
            self.elitist['chromosome'] = self.individuals[j]
            self.elitist['age'] = self.age

    # 遗传算法迭代过程
    def evolve(self):
        self.age += 1
        self.compute_fitness()
        self.compute_select()
        self.select()
        self.mutate()
        self.individuals = self.new_individuals
        self.new_individuals = []
        self.compute_fitness()
        self.reproduct_elitist()

    # 遗传算法迭代
    def run(self):
        for i in range(self.generation_max):
            self.evolve()
        print('迭代结束,当前最佳个体信息如下:')
        print('当前个体的组内各染色体的TARGET_FID分别为:')
        chromosomes = self.elitist['chromosome']
        for i in range(10):
            print(self.data_list[chromosomes[i]][0])
        print("此时的目标函数的值为:", self.elitist['fitness'])


# data_file 数据文件路径
data_file = '/Users/qiguan/Downloads/data.xlsx'
# 数据文件路径为:data_file
# 规模大小:10
# 交叉概率0.2
# 变异概率0.02
# 最大迭代数10
population = Population(data_file, 10, 0.2, 0.02, 10)
population.run()

猜你喜欢

转载自blog.csdn.net/qq_43422111/article/details/107206785