遗传算法工厂模式封装:二进制编码和实数编码
遗传算法工厂模式封装:二进制编码和实数编码
本文展示了如何使用工厂模式封装两种不同遗传算法:二进制基因编码和实数编码。代码示例包括工厂类、个体类、种群类以及相关函数,方便用户根据需要选择不同的编码方式进行遗传算法优化。
代码示例
# 封装工厂类
import math
import random
import time
import copy
class GAFactory:
def __init__(self, problem_type):
self.problem_type = problem_type
self.pop = GAFactory.popu()
class indivi:
def __init__(self):
if self.problem_type == 'binary':
self.gene = ['0'] * (LENIND + 1)
elif self.problem_type == 'real':
self.geneX1 = 0.0
self.geneX2 = 0.0
self.fitness = 0.0
class popu:
def __init__(self):
self.indv = [GAFactory.indivi() for n in range(NUMIND)]
self.bestInd = GAFactory.indivi()
self.generan = 0
def fit(self, x, y, i):
if i == 1:
return self.problem_type == 'binary', x * math.sin(10 * PI * x) + 2.0 if self.problem_type == 'binary' else 3 * (x ** 2 - y) ** 2
else:
return x, y
def dou2ZD(self, x, lowBef, upBef, lowAft, upAft):
return lowAft + (x - lowBef) * (upAft - lowAft) / (upBef - lowBef)
def initPop(self):
self.pop.generan = 0
for indv in self.pop.indv:
if self.problem_type == 'binary':
indv.gene = [str(random.randint(0, 1)) for _ in range(LENIND)]
indv.gene.append('�')
elif self.problem_type == 'real':
indv.geneX1 = random.uniform(0, 1024)
indv.geneX2 = random.uniform(0, 1024)
def calFit(self):
for indv in self.pop.indv:
if self.problem_type == 'binary':
indv.x = self.dou2ZD(self.bin2dou(indv.gene), 0, pow(2, LENIND), -1, 2)
indv.fitness = self.fit(indv.x, 0, FUN)[1]
elif self.problem_type == 'real':
indv.geneX1 = self.dou2ZD(indv.geneX1, 0, 1024, -10, 10)
indv.geneX2 = self.dou2ZD(indv.geneX2, 0, 1024, -10, 10)
indv.fitness = self.fit(indv.geneX1, indv.geneX2, FUN)[1]
def calUp(self):
sum = 0.0
for indv in self.pop.indv:
sum += indv.fitness
self.pop.indv[0].upLim = self.pop.indv[0].fitness / sum
for i in range(NUMIND - 1):
temp = self.pop.indv[i + 1].fitness / sum
self.pop.indv[i + 1].upLim = temp + self.pop.indv[i].upLim
if self.pop.indv[i + 1].upLim > 1.0 and (i + 1) < (NUMIND - 1):
for j in range(NUMIND):
print('generation is:{},fitness={},UpLim={}'.format(self.pop.generan, self.pop.indv[j].fitness,
self.pop.indv[j].upLim))
print('
Error,{}'s upLim is greater than 1=============
'.format(i + 1))
exit(0)
self.pop.indv[NUMIND - 1].upLim = 1
def HalfSear(self, value, LowBo, UpBo, InA):
if LowBo >= UpBo:
return UpBo
Mid = (LowBo + UpBo) // 2
if Mid == 0:
return 0
if value <= InA[Mid] and value > InA[Mid - 1]:
return Mid
else:
if value >= InA[Mid]:
return self.HalfSear(value, Mid, UpBo, InA)
else:
return self.HalfSear(value, LowBo, Mid, InA)
def calSub(self):
poptem = GAFactory.popu()
TemFitn = [indv.upLim for indv in self.pop.indv]
for i in range(NUMIND):
rnd = random.uniform(0, 1)
NumTemp = self.HalfSear(rnd, 0, NUMIND, TemFitn)
poptem.indv[i] = self.pop.indv[NumTemp]
poptem.generan = self.pop.generan
poptem.bestInd = self.pop.bestInd
self.pop = poptem
def select(self):
self.calUp()
self.calSub()
def swithstr(self, s, t):
i = random.randint(1, LENIND - 1)
for j in range(i, LENIND):
temp = s[j]
s[j] = t[j]
t[j] = temp
def bin2dou(self, bp):
retuV = 0
for i in range(LENIND):
tem = 0 if bp[i] == '0' else 1
retuV += tem * pow(2, LENIND - i - 1)
return (retuV)
def crossove(self):
for i in range(NUMIND // 2):
if random.random() > crossPro:
continue
else:
j = random.randint(0, NUMIND - 1)
k = random.randint(0, NUMIND - 1)
if self.problem_type == 'binary':
self.swithstr(self.pop.indv[j].gene, self.pop.indv[k].gene)
elif self.problem_type == 'real':
a = random.uniform(0, 1)
self.pop.indv[j].geneX1 = a * self.pop.indv[j].geneX1 + (1 - a) * self.pop.indv[k].geneX1
self.pop.indv[j].geneX2 = a * self.pop.indv[j].geneX2 + (1 - a) * self.pop.indv[k].geneX2
self.pop.indv[k].geneX1 = a * self.pop.indv[k].geneX1 + (1 - a) * self.pop.indv[j].geneX1
self.pop.indv[k].geneX2 = a * self.pop.indv[k].geneX2 + (1 - a) * self.pop.indv[j].geneX2
def changeM(self, ind):
r = random.randint(0, LENIND - 1)
if ind[r] == '0':
ind[r] = '1'
else:
ind[r] = '0'
def mutation(self):
for i in range(NUMIND):
if random.random() > mutaPro:
continue
else:
if self.problem_type == 'binary':
self.changeM(self.pop.indv[i].gene)
elif self.problem_type == 'real':
self.pop.indv[i].geneX1 = random.uniform(0, 1024)
self.pop.indv[i].geneX2 = random.uniform(0, 1024)
def max(self):
j = 0
tem = self.pop.indv[0].fitness
for i in range(1, NUMIND):
if self.pop.indv[i].fitness > tem:
tem = self.pop.indv[i].fitness
j = i
self.pop.bestInd = copy.deepcopy(self.pop.indv[j])
# 全局变量
PI = 3.1415926
NUMIND = 25
LENIND = 20
FUN = 1
crossPro = 0.9
mutaPro = 0.1
if __name__ == '__main__':
random.seed(time.time() % 9)
# 创建二进制编码遗传算法对象
ga_binary = GAFactory('binary')
ga_binary.initPop()
fp = open('a.txt', 'w')
if not fp:
print('Can't open file')
exit(0)
while ga_binary.pop.bestInd.fitness <= 3.85027 and ga_binary.pop.generan < 10000:
ga_binary.calFit()
ga_binary.max()
print('The generation is {}, the best fitness is {}'.format(ga_binary.pop.generan, ga_binary.pop.bestInd.fitness))
fp.write('Best Individual: {}, {}
'.format(ga_binary.pop.bestInd.gene, ga_binary.pop.bestInd.fitness))
ga_binary.select()
ga_binary.crossove()
if ga_binary.pop.generan == 100:
mutaPro = 0.3
print('The mutation probability is set to 0.3')
ga_binary.mutation()
ga_binary.pop.indv[0] = ga_binary.pop.bestInd
ga_binary.pop.generan += 1
print('finished')
fp.close()
# 创建实数编码遗传算法对象
ga_real = GAFactory('real')
ga_real.initPop()
fp = open('b.txt', 'w')
if not fp:
print('Can't open file')
exit(0)
while ga_real.pop.bestInd.fitness <= 40000 and ga_real.pop.generan < 10000:
ga_real.calFit()
ga_real.max()
print('The generation is {}, the best fitness is {}'.format(ga_real.pop.generan, ga_real.pop.bestInd.fitness))
fp.write('Best Individual: X1={}, X2={}, {}
'.format(ga_real.pop.bestInd.geneX1, ga_real.pop.bestInd.geneX2, ga_real.pop.bestInd.fitness))
ga_real.select()
ga_real.crossove()
if ga_real.pop.generan == 100:
mutaPro = 0.3
print('The mutation probability is set to 0.3')
ga_real.mutation()
ga_real.pop.indv[0] = ga_real.pop.bestInd
ga_real.pop.generan += 1
print('finished')
fp.close()
代码解析
-
工厂类 GAFactory
- 接收
problem_type参数,指定编码方式('binary' 或 'real')。 - 内部定义
indivi类和popu类,分别代表个体和种群,根据编码方式动态创建属性。 - 包含所有遗传算法操作的函数,例如
fit()、initPop()、calFit()等,这些函数根据编码方式进行相应的处理。
- 接收
-
全局变量
- 定义了遗传算法的参数,例如
PI、NUMIND、LENIND等。
- 定义了遗传算法的参数,例如
-
主程序
- 创建两个 GAFactory 对象,分别对应二进制编码和实数编码。
- 使用两个对象分别运行遗传算法,并输出结果。
总结
通过工厂模式封装,我们可以轻松地创建不同编码方式的遗传算法对象,并进行相应的操作。这种方法简化了代码结构,提高了代码的可读性和可维护性。
原文地址: https://www.cveoy.top/t/topic/nyFf 著作权归作者所有。请勿转载和采集!