基因表达式编程(GEP)自学 第【4】天 Python 实现(代码)

发布于:2023-01-22 ⋅ 阅读:(19) ⋅ 点赞:(0) ⋅ 评论:(0)

基因表达式编程 GEP Python 代码实现【★★★★】

今天将用python实现GEP算法中,初始化操作:
生成样本数据、定义函数、参数初始化,生成初始种群

【PS:注意结合前边内容,本次也是首次开始用Python 的编程,如果对一些python库比较陌生的可以边学边看,对于Genome 类,开始可能不清楚为什么这样设置,也不用太纠结。重点在如何初始种群。】

基因表达式编程(GEP)自学 第【1】天 Python 实现
基因表达式编程(GEP)自学 第【2】天 Python 实现
基因表达式编程(GEP)自学 第【3】天 Python 实现

1. 运行环境

运行python是G在PyCharm 运行
在这里插入图片描述

1.1. Python 需要的库

import random
import math
import numpy as np
import sympy

2. Python实现生成数据

为了方便之后边的测试,这里我将自动生成样本数据

GenerateData(DataCount=10)
随机生成样本数据:根据:Function的公式生成
X_Input 保存输入参数
Y_Output 保存输出值
InputsOutputs 保存输入与输出集合

输出格式:
X_Input:
[[3, 1], [1, 1], [0, 4]]
Y_Output:
[[35], [15], [20]]
InputsOutputs:
([[3, 1], [1, 1], [0, 4]], [[35], [15], [20]])

def GenerateData(DataCount=10):
    '''
    随机生成样本数据:根据:Function的公式生成
    X_Input     保存输入参数
    Y_Output    保存输出值
    InputsOutputs 保存输入与输出集合
    输出格式:
    X_Input:
    [[3, 1], [1, 1], [0, 4]]
    Y_Output:
    [[35], [15], [20]]
    InputsOutputs:
    ([[3, 1], [1, 1], [0, 4]], [[35], [15], [20]])
    '''
    X_Input=[]
    Y_Output=[]
    for i in range(DataCount):
        random.seed(i)
        A = random.randint(0, 5)
        random.seed(i+DataCount)
        B = random.randint(0, 5)
        X_Input.append([A,B])
        Y_Output.append([Function(A,B)])
        #---------------输出测试Begin--------------#
        # print("X_Input:\n",X_Input)
        # print("Y_Output:\n",Y_Output)
        # print("InputsOutputs:\n",InputsOutputs)
        #----------------输出测试end---------------#
    InputsOutputs=(X_Input,Y_Output)
    return InputsOutputs

输出结果:

X_Input:
 [[3, 1], [1, 1], [0, 4]]
Y_Output:
 [[35], [15], [20]]
InputsOutputs:
 ([[3, 1], [1, 1], [0, 4]], [[35], [15], [20]])

3. Python 实现初始化

3.1 Genome 类 定义函数、终结符

在初始化前,我们要定义下函数、终结符:

  • PS:传统基因的连接,用的时连接基因而不是全用“+”
    进行连接,因此在定义下函数、终结符中,我将传统基因的终结符与连接基因的终结符分开。同时传统基因的函数集合、与连接基因的函数集合也设置不同的集合
class Genome():
    '''对函数符运算进行定义、终结符定义'''

    def __init__(self):
        '''定义函数、终结符
        functions   保存函数 如:*,/,+,—
        terminals   保存终结符 如:a,b
        genicTerminals 保存连接基因的终结符 如:0,1,2
        '''
        self.functions = {"max_arity": 0}
        self.terminals = []
        self.genicTerminals = range(1)

    #定义 add ,sub ,mul ,div 函数的运算
    #进行div保护,当除数为小于1e-6时,将除数设置为1
    def add(inputs):
        inputs.append(inputs.pop(-2) + inputs.pop(-1))
    def sub(inputs):
        inputs.append(inputs.pop(-2) - inputs.pop(-1))
    def mul(inputs):
        inputs.append(inputs.pop(-2) * inputs.pop(-1))
    def div(inputs):
        if abs(inputs[-1]) < 1e-6:
            inputs[-1] = 1
        inputs.append(inputs.pop(-2) / inputs.pop(-1))

    #运算符特征【'+':2,'-':2,'a':0,'b':0】
    def symbols(self):
        symbols = self.functions.copy()
        symbols.pop("max_arity", None)
        for symbol in symbols.keys():
            symbols[symbol] = symbols[symbol][1]
        symbols.update({terminal: 0 for terminal in self.terminals + list(self.genicTerminals)})
        return symbols

	'''传统基因函数集合、连接基因函数集合:
    对于:{"+": (add, 2),"max_arity": 2}
    +是运算符,add保存是对应的运算,2是需要参数个数
    max_arity 是保存最大需要的参数个数,2是最大需要参数个数'''

    arithmetic_set = {"+": (add, 2), "-": (sub, 2), "*": (mul, 2), "/": (div, 2),"max_arity": 2}
    linker_set = {"+": (add, 2), "-": (sub, 2), "*": (mul, 2), "/": (div, 2),"max_arity": 2}

深度解析 :

arithmetic_set:

‘’‘传统基因函数集合、连接基因函数集合:
对于:{“+”: (add, 2),“max_arity”: 2}
+是运算符,add保存是对应的运算,2是需要参数个数
max_arity 是保存最大需要的参数个数,2是最大需要参数个数’‘’
arithmetic_set = {“+”: (add, 2), “-”: (sub, 2), ““: (mul, 2), “/”: (div, 2),“max_arity”: 2}
linker_set = {”+": (add, 2), “-”: (sub, 2), "
”: (mul, 2), “/”: (div, 2),“max_arity”: 2}

symbols 函数:
作用理解为保留数字特征,
在 arithmetic_set 中保留了
运算符、运算,参数个数、和特别的最大需要的参数个数"max_arity": 2
symbols 作用将保留运算符和特征 如下:
假设self.functions = arithmetic_set
self.terminals = [“a”,“b”]
self.genicTerminals=[“0”]
将运算符特征 arithmetic_set = {“+”: (add, 2), “-”: (sub, 2), “*”: (mul, 2), “/”: (div, 2),“max_arity”: 2}

返回 symbols 为{‘+’: 2, ‘-’: 2, ‘*’: 2, ‘/’: 2, ‘a’: 0, ‘b’: 0, 0: 0}

def symbols(self):
        symbols = self.functions.copy()
        symbols.pop("max_arity", None)
        for symbol in symbols.keys():
            symbols[symbol] = symbols[symbol][1]
        symbols.update({terminal: 0 for terminal in self.terminals + list(self.genicTerminals)})
        return symbols

3.2 初始突变参数、染色体

设计的思路:主要是分为Environment、Chromosome、Gene
简单理解Environment理解为种群;一个种群有多个Chromosome 染色体,而一个Chromosome里有多个Gene 基因。

3.2.1. Environment:

初始化部分:

class Environment:
    def __init__(self):
        '''
        population          种群:用于保存染色体
        bestChromosome      最佳染色体:保存当代最佳染色体
        bestfitness         最佳染色体的适应度:保证当代最佳染色体的适应度
        homeoticRate        连接基因突变率
        mutationRate        突变
        ISTranspositionRate         IS
        RISTranspositionRate        RIS
        geneTranspositionRate       基因转座
        onePointRecombinationRate   单点重组
        twoPointRecombinationRate   两点重组
        geneRecombination           基因重组
        '''

        self.population = []
        self.bestChromosome=[]
        self.bestfitness=0
        self.homeoticRate = 0
        self.mutationRate = 0
        self.ISTranspositionRate = 0
        self.RISTranspositionRate = 0
        self.geneTranspositionRate = 0
        self.onePointRecombinationRate = 0
        self.twoPointRecombinationRate = 0
        self.geneRecombination=0

    def setRates(self, homeoticRate=0, mutationRate=0,ISTranspositionRate=0, RISTranspositionRate=0, geneTranspositionRate=0, onePointRecombinationRate=0, twoPointRecombinationRate=0, geneRecombinationRate=0):
        '''
        homeoticRate        连接基因突变率
        mutationRate        突变
        ISTranspositionRate         IS
        RISTranspositionRate        RIS
        geneTranspositionRate       基因转座
        onePointRecombinationRate   单点重组
        twoPointRecombinationRate   两点重组
        geneRecombination           基因重组
        '''
        self.homeoticRate = homeoticRate
        self.mutationRate = mutationRate
        self.ISTranspositionRate = ISTranspositionRate
        self.RISTranspositionRate = RISTranspositionRate
        self.geneTranspositionRate = geneTranspositionRate
        self.onePointRecombinationRate = onePointRecombinationRate
        self.twoPointRecombinationRate = twoPointRecombinationRate
        self.geneRecombinationRate = geneRecombinationRate

    def init(self, populationSize, numGenes, numHomeotics, headLength, homeoticHeadLength, genome,link_genome):
        '''
        初始化种群
        populationSize      种群大小
        numGenes            染色体基因个数
        numHomeotics        染色体连接基因个数
        headLength          基因头部长度
        homeoticHeadLength  连接基因头部长度
        genome              基因 Genome类
        link_genome         连接 link_genome 类
        '''
        self.population = [Chromosome().initRand(numGenes, numHomeotics, headLength, homeoticHeadLength, genome,link_genome) for i in range(populationSize)]

3.2.2. Chromosome :

初始化部分

class Chromosome():
    def __init__(self):
        '''
        genes           基因:用于保存传统基因
        homeotics       连接基因:用于保存连接基因
        '''
        self.genes = []
        self.homeotics = []
    #染色体(基因、连接函数)
    def initRand(self, numGenes, numHomeotics, headLength, homeoticHeadLength, genome, link_genome):
        '''
        初始化染色体
        :param numGenes:        基因个数
        :param numHomeotics:    连接基因个数
        :param headLength:      基因头部长度
        :param homeoticHeadLength:      连接基因头部长度
        :param genome:                  基因 Genome
        :param link_genome:             连接基因 Genome
        :return self:
        genes           基因:用于保存传统基因
        homeotics       连接基因:用于保存连接基因
        '''
        self.genes = [Gene(genome, False).initRand(headLength, numGenes) for i in range(numGenes)]
        self.homeotics = [Gene(link_genome, True).initRand(homeoticHeadLength, numGenes) for i in range(numHomeotics)]
        return self

3.2.1. Gene:

初始化部分

class Gene():
    def __init__(self, genome, homeotic_flag):
        '''
        genome:         基因的 Genome
        homeotic_flag:  Flag值 True:为homeotic基因 False: 为传统基因
        head            基因头部
        tail            基因尾部
        '''
        self.genome = genome
        self.homeotic_flag = homeotic_flag
        self.head = []
        self.tail = []

    def initRand(self, headLength, numGenes):
        '''
        :param headLength:      基因头部长度
        :param numGenes:        基因个数
        :return:self

        max_arity       保存最大需要的参数个数
        functions       保存Genome中操作符 如:["+","-","*","/"]
        homeotic_flag:  Flag值 True:为homeotic基因 False: 为传统基因
        '''
        max_arity = self.genome.functions["max_arity"]
        functions = list(self.genome.functions.keys())
        functions.pop(functions.index("max_arity")) # functions中剔除max_arity
        
        #生成homeotic的terminals、
        if self.homeotic_flag:
            terminals = list(range(numGenes))
            if numGenes > list(self.genome.genicTerminals)[-1]:
                self.genome.genicTerminals = range(numGenes)
        else:
            terminals = self.genome.terminals
        self.head = [random.choice(functions + terminals) for i in range(headLength)]
        self.tail = [random.choice(terminals) for i in range(headLength * (max_arity - 1) + 1)]
        #基因首个为运算符
        self.head[0] = random.choice(functions)
        return self

3.3 打印染色体

为了更好的我们的观察:
我们在Environment中在定义个函数 printChromosomes用于打印染色体

 def printChromosomes(self, generation):
        '''
        打印染色体
        :param generation:   迭代的代数
        :return: None
        '''
        print(generation)
        for i in range(len(self.population)):
            print(i, ':', end='')
            for gene in self.population[i].genes:
                print(gene.head + gene.tail, end=':')
            for homeotic in self.population[i].homeotics:
                print(homeotic.head + homeotic.tail, end=':')
            print()
        print()

4. 初始化输出测试

if __name__=='__main__':

    #---------------操作数设置 Begin--------------#
    genome = Genome()
    genome.functions.update(Genome.linker_set)
    genome.terminals = ['a','b']
    genome.symbols()
    my_link_genome=Genome()
    my_link_genome.functions.update(Genome.linker_set)
    #----------------操作数设置 end---------------#


    #---------------种群初始化 Begin--------------#
    environment = Environment()
    environment.init(populationSize=20,numGenes=3,numHomeotics=1,headLength=4,homeoticHeadLength=5,genome=genome,link_genome=my_link_genome)
    environment.setRates(homeoticRate=0.5, mutationRate=0.044,ISTranspositionRate=0.1,
                         RISTranspositionRate=0.1, geneTranspositionRate=0.1,onePointRecombinationRate=0.3,
                         twoPointRecombinationRate=0.3, geneRecombinationRate=0.1)
    ##----------输出测试----------##
    environment.printChromosomes(0)
    #----------------种群初始化 end---------------#

输出结果:

1
0 :['+', '+', '+', 'b', 'a', 'b', 'a', 'a', 'b']:['+', '/', '/', '-', 'b', 'a', 'b', 'b', 'a']:['/', '-', '-', 'b', 'b', 'b', 'b', 'a', 'b']:['-', '*', 2, 0, 2, 2, 2, 2, 0, 0, 1]:
1 :['/', '-', '*', '-', 'b', 'b', 'a', 'a', 'b']:['*', 'a', 'a', '+', 'a', 'b', 'b', 'b', 'a']:['*', 'a', '-', 'b', 'b', 'b', 'a', 'b', 'a']:['+', 2, 1, '+', 1, 1, 0, 1, 2, 1, 0]:
2 :['/', '+', 'b', '-', 'a', 'b', 'b', 'b', 'b']:['-', '+', '/', 'a', 'b', 'b', 'a', 'a', 'b']:['*', 'b', '-', 'a', 'a', 'b', 'b', 'a', 'a']:['-', '/', '/', 2, 1, 0, 1, 2, 1, 1, 2]:
3 :['*', '+', 'b', 'a', 'a', 'b', 'a', 'b', 'a']:['+', '-', 'a', '+', 'b', 'a', 'a', 'a', 'a']:['*', '+', '/', '*', 'a', 'b', 'a', 'a', 'a']:['/', '+', 1, 1, 2, 0, 0, 0, 2, 2, 0]:
4 :['*', '*', 'b', '-', 'a', 'b', 'a', 'b', 'a']:['+', '/', '*', 'b', 'a', 'b', 'a', 'a', 'a']:['-', '+', 'b', '/', 'b', 'a', 'a', 'b', 'b']:['*', '-', '-', '+', '*', 1, 0, 2, 0, 2, 2]:
5 :['+', '-', '-', '*', 'a', 'a', 'a', 'b', 'b']:['*', '+', '-', 'a', 'a', 'b', 'a', 'b', 'b']:['+', '/', 'b', '-', 'a', 'b', 'b', 'b', 'a']:['+', '/', '+', '+', '-', 1, 2, 1, 1, 2, 1]:
6 :['+', '+', 'b', '/', 'a', 'a', 'a', 'a', 'a']:['*', '+', '-', '+', 'b', 'a', 'a', 'b', 'a']:['*', '*', '-', '+', 'b', 'a', 'b', 'a', 'b']:['-', '*', '/', 0, '+', 2, 1, 0, 0, 1, 0]:
7 :['*', 'b', '-', '-', 'a', 'a', 'a', 'a', 'b']:['/', '+', '+', '/', 'b', 'b', 'a', 'a', 'a']:['*', 'b', '*', '*', 'b', 'a', 'a', 'a', 'b']:['-', '/', '+', 0, '-', 2, 0, 2, 2, 2, 1]:
8 :['-', '-', '*', '+', 'b', 'b', 'b', 'a', 'b']:['*', '*', 'b', 'b', 'b', 'a', 'a', 'b', 'b']:['*', '*', '-', '*', 'a', 'b', 'a', 'a', 'a']:['*', '-', '*', 2, '/', 2, 1, 1, 2, 2, 1]:
9 :['*', '*', '+', 'b', 'b', 'a', 'a', 'a', 'a']:['/', 'a', 'b', '-', 'b', 'a', 'a', 'a', 'a']:['+', '-', '*', '*', 'a', 'b', 'b', 'a', 'a']:['/', '*', '*', '-', 0, 2, 2, 2, 0, 1, 1]:
10 :['-', '+', 'b', '/', 'b', 'a', 'a', 'b', 'b']:['*', 'a', '/', 'b', 'b', 'b', 'b', 'b', 'b']:['-', '*', '+', '/', 'b', 'b', 'a', 'a', 'b']:['+', 1, '+', '/', '/', 0, 2, 2, 2, 1, 2]:
11 :['+', '*', '-', 'b', 'b', 'b', 'b', 'a', 'b']:['*', '+', 'b', 'b', 'b', 'b', 'a', 'b', 'a']:['*', 'b', '-', '/', 'b', 'a', 'a', 'a', 'a']:['*', '-', '/', 0, '+', 1, 0, 0, 0, 0, 2]:
12 :['-', 'b', 'a', 'a', 'b', 'b', 'b', 'b', 'b']:['-', '-', '+', 'b', 'b', 'a', 'b', 'b', 'b']:['/', 'b', '-', '*', 'a', 'b', 'a', 'b', 'b']:['*', 2, '*', 1, '-', 2, 2, 0, 2, 1, 0]:
13 :['*', 'a', 'a', '+', 'b', 'a', 'a', 'a', 'a']:['*', '+', '*', '-', 'b', 'a', 'b', 'a', 'a']:['/', '-', 'b', 'b', 'a', 'a', 'b', 'b', 'a']:['+', '/', '+', 1, 2, 1, 0, 0, 2, 1, 1]:
14 :['-', '-', '*', '*', 'b', 'b', 'b', 'b', 'b']:['+', '*', 'a', 'b', 'a', 'a', 'b', 'a', 'a']:['*', '/', 'b', '+', 'a', 'b', 'a', 'b', 'a']:['*', 2, '-', '/', 2, 0, 2, 1, 2, 1, 0]:
15 :['/', '-', 'b', '+', 'b', 'b', 'b', 'a', 'a']:['*', '*', '*', '/', 'b', 'a', 'a', 'a', 'b']:['-', '-', '/', '*', 'a', 'b', 'a', 'b', 'a']:['-', 1, '/', '*', 0, 0, 2, 1, 2, 2, 0]:
16 :['+', '/', '/', '*', 'b', 'b', 'a', 'b', 'b']:['-', '/', 'a', 'a', 'b', 'a', 'a', 'b', 'b']:['/', '*', '*', 'b', 'b', 'a', 'b', 'a', 'a']:['-', '+', '+', '*', 0, 2, 2, 0, 2, 0, 0]:
17 :['/', '/', 'a', '/', 'b', 'a', 'a', 'b', 'b']:['/', '*', 'a', 'b', 'b', 'a', 'a', 'b', 'a']:['+', '+', '-', '-', 'a', 'b', 'b', 'a', 'b']:['*', 2, 0, '-', 0, 2, 2, 1, 0, 1, 2]:
18 :['*', 'a', 'b', 'b', 'b', 'b', 'a', 'b', 'b']:['*', '-', '*', '-', 'a', 'b', 'b', 'b', 'b']:['-', '+', '/', '-', 'a', 'a', 'b', 'b', 'a']:['*', 2, 0, '+', '-', 2, 1, 0, 2, 0, 1]:
19 :['/', 'b', '-', '/', 'b', 'b', 'b', 'a', 'b']:['/', 'b', '/', '*', 'b', 'a', 'a', 'b', 'b']:['*', '*', 'a', '-', 'b', 'a', 'a', 'a', 'b']:['*', '-', 0, 0, '-', 1, 0, 1, 2, 1, 0]:

5. 代码实现整合:

为了方便演示,我将每个类整合到一个py文件上,GEP-4 初始化实现.py.

本文作者:九重!
本文链接:https://blog.csdn.net/weixin_43798572/article/details/122823927
关于博主:评论和私信会在第一时间回复。或者直接私信我。
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【点赞】【收藏】一下。您的鼓励是博主的最大动力!


网站公告

欢迎关注微信公众号

今日签到

点亮在社区的每一天
签到