基因表达式编程 GEP Python 代码实现
今天将用python实现GEP算法中,初始化操作: 生成样本数据、定义函数、参数初始化,生成初始种群
PS:注意结合前边内容
基因表达式编程(GEP)自学 第【1】天 Python 实现 基因表达式编程(GEP)自学 第【2】天 Python 实现 基因表达式编程(GEP)自学 第【3】天 Python 实现
1. 运行环境
运行python是在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]])
-
return 8*a+4*b+2*a*b+b
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)])
InputsOutputs=(X_Input,Y_Output)
print("X_Input:\n",X_Input)
print("Y_Output:\n",Y_Output)
print("InputsOutputs:\n",InputsOutputs)
输出结果:
```python
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)
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))
def log10(inputs):
if inputs[-1]<=0:
inputs[-1]=math.e
inputs.append(math.log10(inputs.pop(-1)))
def log2(inputs):
if inputs[-1]<=0:
inputs[-1]=math.e
inputs.append(math.log2(inputs.pop(-1)))
def ln(inputs):
if inputs[-1]<=0:
inputs[-1]=math.e
inputs.append(math.log(inputs.pop(-1),math.e))
def log(inputs):
if inputs[-1]<=0:
inputs[-1]=math.e
if inputs[-2]<=0 or inputs[-2]==1:
inputs[-2]=math.e
inputs.append(math.log(inputs.pop(-2),inputs.pop(-1)))
def sin(inputs):
inputs.append(math.sin(inputs.pop(-1)))
def cos(inputs):
inputs.append(math.cos(inputs.pop(-1)))
def tan(inputs):
inputs.append(math.tan(inputs.pop(-1)))
def sqrt(inputs):
if inputs[-1]<0:
inputs[-1]=1
inputs.append(math.sqrt(inputs.pop(-1)))
def NOT(inputs):
inputs.append(not inputs.pop(-1))
def AND(inputs):
inputs.append(inputs.pop(-2) and inputs.pop(-1))
def OR(inputs):
inputs.append(inputs.pop(-2) or inputs.pop(-1))
def XOR(inputs):
inputs.append(inputs.pop(-2) is not inputs.pop(-1))
def XNOR(inputs):
inputs.append(inputs.pop(-2) is inputs.pop(-1))
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"))
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__':
genome = Genome()
genome.functions.update(Genome.linker_set)
genome.terminals = ['a','b']
genome.symbols()
my_link_genome.functions.update(Genome.linker_set)
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(1)
输出结果:
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 关于博主:评论和私信会在第一时间回复。或者直接私信我。 声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【点赞】【收藏】一下。您的鼓励是博主的最大动力!
|