简单遗传算法Python实现

简单遗传算法Python实现

本文是用Python语言写的遗传算法,初次尝试,效率不高,但能较好地理解简单的遗传算法。
在实际应用中,推荐学习geatpy库。

算法代码

import numpy as np


class Ga:
    @classmethod
    def codeit(cls, n, length):
        #
        # 创建初始群体
        # 传入参数, 初始群体数量n, 编码长度length
        # 返回初始群体编码列表
        #
        inipol = []
        for i in range(n):
            tempb = ""
            for j in range(length):
                data = np.random.choice([0, 1])
                tempb += str(data)
            inipol.append(tempb)
        return inipol

    @classmethod
    def decodeit(cls, coding, lowest, ranges):
        #
        # 解码
        # 传入参数, 编码coding, 可行域最小值lowest, 取值长度ranges
        # 返回解码列表decoding
        #
        decoding = np.copy(coding).tolist()
        length = len(decoding[0])
        for i in range(len(decoding)):
            decoding[i] = np.round(lowest + int(decoding[i], base=2)*ranges/(2**length-1), 3)
        return decoding

    @staticmethod
    def fits(x):
        #
        # 适应度函数
        #
        return x + 10*np.sin(5*x) + 7*np.cos(4*x)

    @classmethod
    def fitnessevaluations(cls, decoding):
        #
        # 个体适应度评价
        # 传入参数,解码decoding
        # 返回个体适应度值列表fitnessvalues
        #
        fitnessvalues = []
        for i in decoding:
            fitnessvalues.extend([np.round(Ga.fits(i), 3)])
        return fitnessvalues

    @classmethod
    def copyoperator(cls, coding, fitnessvalues):
        #
        # 复制算子
        # 传入参数,编码coding,适应度值fitnessvalues
        # 返回复制算子编码copycoding
        #
        copycoding = np.copy(coding).tolist()
        minindex = fitnessvalues.index(min(fitnessvalues))
        maxindex = fitnessvalues.index(max(fitnessvalues))
        copycoding[minindex] = copycoding[maxindex]
        copycoding[minindex] = copycoding[maxindex]
        return copycoding

    @classmethod
    def crossoveroprator(cls, copycoding, crossoverposssibility):
        #
        # 杂交算子
        # 参入参数,复制算子编码copycoding,杂交概率crossoverposibility
        # 返回杂交算子编码crossovercoding
        #
        crossovercoding = np.copy(copycoding).tolist()
        copysave = []
        crossover = []
        for i in range(int(len(crossovercoding)*crossoverposssibility)):
            copysave.append(crossovercoding[i])
        for i in range(int(len(crossovercoding) * (1-crossoverposssibility))):
            crossover.append(crossovercoding[-i-1])
        crossoverpoit = len(crossovercoding)-1
        for i in range(int(len(crossover)/2)):
            crossover[i], crossover[-i-1] = \
                crossover[i][:crossoverpoit]+crossover[-i-1][crossoverpoit:], \
                crossover[-i - 1][:crossoverpoit] + crossover[-i][crossoverpoit:]
        crossovercoding = copysave + crossover
        return crossovercoding

    @classmethod
    def mutationoprator(cls, crossovercoding, mutationpossibility, lowest, ranges):
        #
        # 变异算子
        # 传入参数, 杂交算子编码crossovercoding,变异概率crossoverpossibility
        # 可行域最小值lowest, 取值长度ranges,
        # 返回变异算子编码
        #
        mutationcoding = np.copy(crossovercoding).tolist()
        crossoverfitnessvalues = Ga.fitnessevaluations(Ga.decodeit(mutationcoding, lowest, ranges))
        tempfitvaleus = np.copy(crossoverfitnessvalues).tolist()
        tempfitvaleus.sort()
        mutationvalues = []
        for i in range(int(len(tempfitvaleus)*mutationpossibility)):
            mutationvalues.append(tempfitvaleus[i])
        mutaionindex = []
        for i in mutationvalues:
            mutaionindex.append(crossoverfitnessvalues.index(i))
        mutationposition = np.random.randint(0, len(mutationcoding[0]))
        for i in mutaionindex:
            if int(mutationcoding[i][mutationposition]) == 1:
                mutationcoding[i] = mutationcoding[i][:mutationposition] + '0' + mutationcoding[i][mutationposition+1:]
            else:
                mutationcoding[i] = mutationcoding[i][:mutationposition] + '1' + mutationcoding[i][mutationposition + 1:]
        return mutationcoding

测试代码

from genetic_algorithm.ga import Ga as ga
import matplotlib.pyplot as plt
import numpy as np


def multiply(coding):
    #
    # 繁衍一代
    # 传入参数,上一代编码coding
    # 返回,新一代编码mutationcoding,新一代解码值decoding,新一代适应度值fitnessvalues
    #
    inipol = coding
    decoding = ga.decodeit(inipol, boudary[0], brange)
    fitnessvalues = ga.fitnessevaluations(decoding)
    copycoding = ga.copyoperator(inipol, fitnessvalues)
    crossovercoding = ga.crossoveroprator(copycoding, crossoverpossibility)
    mutationcoding = ga.mutationoprator(crossovercoding, mutationpossibility, boudary[0], brange)
    return mutationcoding, decoding, fitnessvalues


def generateit():
    #
    # 繁衍多代
    # 返回,最终编码coding,每次繁衍的编码decodings,每次繁衍的适应度值fitnessvalues,初始编码iniplot,每代的适应度值fitness
    #
    inipol = ga.codeit(n, length)
    decodings = []
    fitnessvalues = []
    fitness = []
    iniplot = np.copy(inipol).tolist()
    for i in range(g):
        inipol = multiply(inipol)[0]
        decodings.append(multiply(inipol)[1])
        fitnessvalues.append(multiply(inipol)[2])
        fitness.append(np.mean(multiply(inipol)[2]))
    return inipol, decodings, fitnessvalues, iniplot, fitness


def plotit():
    plt.rcParams['font.family'] = 'SimHei'
    plt.rcParams['axes.unicode_minus'] = False
    inicoding = generateit()[3]
    inidecoding = ga.decodeit(inicoding, boudary[0], brange)
    initfittness = ga.fitnessevaluations(inidecoding)
    decoding = generateit()[1][-1]
    fitnessvalue = generateit()[2][-1]
    fitness = generateit()[4]
    x = np.linspace(boudary[0], boudary[1], 1000)
    fits = x + 10*np.sin(5*x) + 7*np.cos(4*x)
    plt.suptitle("简单遗传算法")
    plt.subplot(121)
    ax = plt.gca()
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)
    plt.plot(x, fits)                                  # 适应度曲线
    plt.scatter(inidecoding, initfittness, c='blue')  # 初始编码
    plt.scatter(decoding, fitnessvalue, c='red')      # 进化后的编码
    plt.xlabel("编码")
    plt.ylabel("适应度值")
    plt.title("适应度曲线")
    plt.subplots_adjust(wspace=0.5)
    plt.subplot(122)
    ax = plt.gca()
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)
    plt.plot(range(g), [j for j in fitness])         # 适应度值变化曲线
    plt.xlabel("进化次数")
    plt.ylabel("适应度值")
    plt.title("适应度值变化曲线")
    plt.savefig("简单遗传算法")


if __name__ == "__main__":
    boudary = [0, 10]  # 变量范围
    brange = boudary[1] - boudary[0]
    accuracy = 1 / 1000  # 精度
    n = 50  # 初始群体数量
    g = 100  # 代
    crossoverpossibility = 0.65  # 杂交概率
    mutationpossibility = 0.05  # 变异概率
    length = int(np.rint(np.log2(brange / accuracy)))  # 编码长度
    with open("初始编码.txt", 'w', encoding="utf-8") as f:
        for i in generateit()[3]:
            f.writelines(i+'\n')
    with open("进化编码.txt", 'w', encoding="utf-8") as f:
        for i in generateit()[0]:
            f.writelines(i + '\n')
    with open("进化解码.txt", 'w', encoding="utf-8") as f:
        for i in generateit()[1][-10:]:
            f.writelines(str(i)+'\n')
    with open("进化适应度值.txt", 'w', encoding="utf-8") as f:
        for i in generateit()[2][-10:]:
            f.writelines(str(i)+'\n')
    plotit()


猜你喜欢

转载自blog.csdn.net/weixin_40775077/article/details/84311631