简易的遗传算法,使用时需要按照自己的需求修改fitness_func 函数
import random
def fitness_func(code):
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.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)
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()