本文章提供了一个基本遗传算法,以求解函数:
其中 ,求解该函数的最大值来解释遗传算法。
遗传算法流程:
Step1. 初始化规模为N的种群,以及每个个体的染色体数目M,采用随机数生成每个个体的所有染色体;
Step2. 采用评估函数,对种群中的所有个体的所有染色体计算其适应值,并得到所有个体中染色体组的最佳适应值;
Step3. 采用轮盘赌选择算法对群体的染色体进行选择操作,产生规模同样为N的种群;
Step4. 按照概率Pc,从种群中选择染色体进行交配。每两个进行交配的父代染色体,交换部分基因,产生两个新的子代染色体,子代染色体取代父代染色体进入新种群。没有进行交配的染色体直接复制进入新种群;
Step5. 按照概率Pm,对新种群中染色体的基因进行变异操作。发生变异的基因数值发生改变。变异后的染色体取代原有染色体进入新群体,未发生变异的染色体直接进入新群体;
Step6. 变异后的新群体取代原有群体,重新计算群体中各个染色体的适应值。倘若群体的最大适应值大于Best的适应值,则以该最大适应值对应的染色体替代Best;
Step7. 当前进化代数Generation加1。如果Generation超过规定的最大进化代数或Best达到规定的误差要求,算法结束;否则返回Step3。
完整代码:
import random
import numpy as np
# 以求一个函数最大值为例,使用遗传算法进行问题求解
# 目标函数,其中x1,x2,x3,x4的取值范围[-5, 5]
def goal_function(x1, x2, x3, x4):
return 1 / (x1**2 + x2**2 + x3**2 + x4**2 + 1)
class SGA:
def __init__(self, group_size, chrom_num):
self.group_size = group_size # 群体规模
self.chrom_num = chrom_num # 染色体数目
self.best = np.zeros(self.chrom_num)
self.generation = 0 # 遗传代数
self.best_value = 0
def initialize(self):
group = np.random.uniform(low=-5, high=5, size=(self.group_size, self.chrom_num))
return group
def evaluate(self, group):
self.eval = np.zeros(self.group_size)
max_adaption = 0
idx = 0
print("群体中个体适应值为:")
for i in range(self.group_size):
self.eval[i] = goal_function(group[i][0],group[i][1],group[i][2],group[i][3])
if self.eval[i] > max_adaption:
max_adaption = self.eval[i]
idx = i
print(f"{i+1}号个体的染色体为:{group[i]}, 适应值为:{self.eval[i]}")
if max_adaption > self.best_value:
self.best = group[idx]
self.best_value = max_adaption
print(f"{idx+1}号个体适应值最大为:{max_adaption}\n")
# 采用轮盘赌算法进行选择
def selection(self, group):
print("轮盘赌算法选择个体进行交配")
total = np.sum(self.eval)
possibility = self.eval / total
new_group = np.zeros([self.group_size, self.chrom_num])
for i in range(self.group_size):
r = np.random.random()
idx = 0
total_poss = possibility[idx]
while r > total_poss:
idx = idx + 1
total_poss = total_poss + possibility[idx]
new_group[i] = group[idx]
print(f"第{i+1}次生成的随机数为:{r},根据轮盘赌选中的个体为:{idx+1}号染色体为:{group[idx]}")
return new_group
def crossover(self, group):
new_group = self.selection(group)
Pc = np.random.uniform(0.4, 0.99)
crossover_select = []
crossover = []
generation = np.zeros([self.group_size, self.chrom_num])
for i in range(self.group_size):
r = np.random.random()
if r > Pc:
crossover_select.append(new_group[i])
else:
crossover.append(new_group[i])
if len(crossover_select) <= 1:
print(f"选择交配的样本数量为:{len(crossover_select)},选择样本数量不足,拒绝交配\n")
for i in range(self.group_size):
generation[i] = group[i]
print(f"后代中{i + 1}号的染色体为:{generation[i]}")
return generation
print(f"选择交配的样本数量为:{len(crossover_select)},选择样本数量充足,开始交配")
while len(crossover_select) > 1:
# 选择交配样本
father_idx = np.random.choice(len(crossover_select))
father = crossover_select[father_idx]
crossover_select.pop(father_idx)
mother_idx = np.random.choice(len(crossover_select))
mother = crossover_select[mother_idx]
crossover_select.pop(mother_idx)
models = ['single', 'mult', 'uniform']
pattern = random.choice(models)
print(f"选择父本为:{father},选择母本为:{mother},交配模式为:{pattern}")
if pattern == 'single':
chrom_idx = random.sample(range(self.chrom_num), 1)
temp = father[chrom_idx]
father[chrom_idx] = mother[chrom_idx]
mother[chrom_idx] = temp
if pattern == 'mult':
num = random.randint(1, self.chrom_num)
chrom_idxs = random.sample(range(self.chrom_num), num)
for chrom_idx in chrom_idxs:
temp = father[chrom_idx]
father[chrom_idx] = mother[chrom_idx]
mother[chrom_idx] = temp
if pattern == 'uniform':
for i in range(self.chrom_num):
p = random.choice([0, 1])
if p == 1:
temp = father[i]
father[i] = mother[i]
mother[i] = temp
crossover.append(father)
crossover.append(mother)
if len(crossover_select) == 1:
crossover.append(crossover_select[0])
for i in range(len(crossover)):
generation[i] = crossover[i]
print(f"后代中{i+1}号的染色体为:{generation[i]}")
print("交配完成\n")
return generation
def variation(self, group):
print("开始变异")
Pm = np.random.uniform(0.7, 0.99)
for i in range(self.group_size):
for j in range(self.chrom_num):
p = random.random()
if p > Pm:
group[i][j] = random.random()
print("变异完成\n")
return group
def train(self, iter_num=50):
generation = self.initialize()
for iter in range(iter_num):
print(f"-------------------------------开始第{iter+1}训练----------------------------------------------")
self.evaluate(generation)
generation = self.crossover(generation)
generation = self.variation(generation)
self.evaluate(generation)
print(f"当前迭代次数为:第{iter+1}次,得到的最大值为:{self.best_value},对应的个体为:{self.best}")
if __name__ == '__main__':
np.set_printoptions(suppress=True, precision=9)
sga =SGA(5, 4)
sga.train(iter_num=150)