简易的遗传算法,使用时需要按照自己的需求修改fitness_func 函数
import random
def fitness_func(code):
# code 为01字符串
c_value = int(code, 2)
return -(c_value - 1) * (c_value - 41) * (c_value - 480)
class GA(object):
def __init__(self, fit_func, code_length=10, individual_number=100,
iterate_number=100, mutate_rate=0.001, elimination_rate=0.1, not_copy_rate=0.001,
nor_drop_rate=0.001):
"""
:param fit_func: 适应度函数
:param code_length: 基因长度
:param individual_number: 种群个体数量
:param iterate_number: 种群迭代次数
:param mutate_rate: 变异概率
:param elimination_rate: 种群淘汰率
:param not_copy_rate: 最优个体不复制概率
:param nor_drop_rate: 淘汰个体不淘汰概率
"""
# 基因的长度
self.ga_code_length = code_length - 1
# 种群中个体数量
self.individual_number = individual_number
# 种群迭代次数
self.iterate_number = iterate_number
# 适应度函数
self.ga_fit_func = fit_func
# 基因库
self.ga_lists = []
# 初始化基因库
self.random_gene()
# 下一代的基因库
self.next_gene_list = []
# 最佳个体
self.best_individual = None
# 最佳个体的适应度值
self.best_score = 0
# 变异概率
self.mutate_rate = mutate_rate
# 淘汰概率
self.elimination_rate = elimination_rate
# 直接复制中不被复制的概率 模拟意外事故的发生
self.not_copy_rate = not_copy_rate
# 直接剔除中 不被剔除的概率 模拟意外保留非最优事件
self.nor_drop_rate = nor_drop_rate
# 检查参数是否设置在正常范围
self.check_init_parameter()
def check_init_parameter(self):
assert 0 < self.not_copy_rate < 1, 'not_copy_rate 范围为(0,1)'
assert 0 < self.nor_drop_rate < 1, 'nor_drop_rate 范围为(0,1)'
assert 0 < self.mutate_rate < 1, 'mutate_rate(变异概率) 范围为(0,1)'
assert 0 < self.elimination_rate < 1, 'elimination_rate(淘汰比例) 范围为(0,1)'
# 随机生成基因库
def random_gene(self):
for ii in range(self.individual_number):
code = random.randint(0, 2 ** self.ga_code_length) | 2 ** (self.ga_code_length + 1)
code = bin(code)[-(self.ga_code_length + 1):]
self.ga_lists.append(code)
# 复制
def ga_copy(self, code):
if random.random() > self.not_copy_rate:
self.next_gene_list.append(code)
# 交叉
def ga_cross(self, code_list):
code_list_len = len(code_list)
temp = code_list_len // 2
if code_list_len % 2 != 0:
# code_list 不为偶数 从code_list 中随机复制一条添加进去
code_list.append(code_list[random.randint(0, code_list_len - 1)])
temp += 1
# 顺序交叉 保证每个基因均被交叉
for ii in range(temp):
a, b = self._cross_gene(code_list[ii], code_list[ii + temp])
self.next_gene_list.append(a)
self.next_gene_list.append(b)
# 随机交叉 补充基因库 保证基因库总基因数量不变 避免奇数问题,多增加一组 后面通过切片剔除
for _ in range((self.individual_number - len(self.next_gene_list)) // 2 + 1):
a, b = self._cross_gene(code_list[random.randint(0, code_list_len - 1)],
code_list[random.randint(0, code_list_len - 1)])
self.next_gene_list.append(a)
self.next_gene_list.append(b)
# 切片剔除多余基因段
self.next_gene_list = self.next_gene_list[:self.individual_number]
# 基因段交叉函数
def _cross_gene(self, code1, code2):
r = random.randint(0, self.ga_code_length)
code1_a, code1_b = code1[:r], code1[r:]
code2_a, code2_b = code2[:r], code2[r:]
return code1_a + code2_b, code2_a + code1_b
# 变异
def ga_mutate(self):
if random.random() < self.mutate_rate:
r_number = random.randint(0, self.individual_number - 1)
r_gene_index = random.randint(0, self.ga_code_length - 1)
self.next_gene_list[r_number] = self._mutate(self.next_gene_list[r_number], r_gene_index)
@staticmethod
def _mutate(code, index):
cl = list(code)
if cl[index] == '0':
cl[index] = '1'
else:
cl[index] = '0'
code = ''.join(cl)
return code
# 丢弃函数 这其中有概率不丢弃
def drop(self, code):
if random.random() < self.nor_drop_rate:
self.next_gene_list.append(code)
# 进化到下一代
def ga_evolute(self):
self.next_gene_list = []
fitness_score = []
for item in self.ga_lists:
fitness_score.append(self.ga_fit_func(item))
# 最大的适应度
max_fs = max(fitness_score)
# 最小的适应度
min_fs = min(fitness_score)
# 适应度大于该值 执行交叉操作 (适应度在10%之上)
cross_score = self.elimination_rate * (max_fs - min_fs) + min_fs
# 这里应该需要修改为轮盘赌的形式 还未修改
cross_list = []
for gene, fs in zip(self.ga_lists, fitness_score):
# 保留最佳个体
if fs == max_fs:
self.ga_copy(gene)
cross_list.append(gene)
elif fs > cross_score:
cross_list.append(gene)
else:
self.drop(gene)
self.ga_cross(cross_list)
self.ga_mutate()
self.ga_lists = self.next_gene_list[:]
self.next_gene_list = []
def get_best(self):
bs = self.ga_fit_func(self.ga_lists[0])
bi = self.ga_lists[0]
for item in self.ga_lists:
if self.ga_fit_func(item) > bs:
bs = self.ga_fit_func(item)
bi = item
# 最大的适应度
self.best_score = bs
self.best_individual = bi
print('best_score=', bs)
print('best_individual=', int(bi, 2))
def fit(self):
for _ in range(self.iterate_number):
self.ga_evolute()
if __name__ == "__main__":
ga = GA(fitness_func, iterate_number=1000)
ga.fit()
ga.get_best()