遗传算法
遗传算法 (Genetic Algorithm,GA) 是模拟生物在自然环境中的遗传和进化的过程而形成的自适应 全局优化搜索算法。
遗传算法借鉴了达尔文的进化论和孟德尔的遗传学说。其本质是一种并行、高效、全局搜索的方法, 它能在搜索过程中自动获取和积累有关搜索空间的知识,并自适应地控制搜索过程以求得最优解。遗传 算法操作使用 “适者生存” 的原则,在潜在的解决方案种群中逐次产生一个近似最优的方案。在遗传算 法的每一代中,根据个体在问题域中的适应度值和从自然遗传学中借鉴来的再造方法进行个体选择,产 生一个新的近似解。这个过程导致种群中个体的进化,得到的新个体比原个体更能适应环境,就像自然 界中的改造一样。
算法流程
以下流程图显示了基本遗传算法流程的主要阶段:
Step1: 种群初始化:进行随机初始化每个个体的染色体的基因型。
Step2: 迭代设置:设置迭代次数
g
m
a
x
g_{max}
gmax,令当前迭代次数
g
=
1
g=1
g=1。
Step3: 染色体解码,根据染色体的表现型计算个体适应度。
Step4: 适者生存,只有优秀的个体才能存活,即对个体进行选择操作。
Step5: 产生下一代个体,即对染色体进行交叉、变异操作。
Step6: 终止条件判断:判断迭代次数时都达到
g
m
a
x
g_{max}
gmax或误差是否足够小,如果满足则输出染色体的表现型和适应值;否则继续进行跌代,跳转至Step3。
代码
求Rastrigin函数的最小值。
Rastrigin函数:
f
(
x
,
y
)
=
2
a
+
x
2
−
a
cos
2
π
x
+
y
2
−
a
cos
2
π
y
\mathrm{f}(\mathrm{x}, \mathrm{y})=2 \mathrm{a}+\mathrm{x}^2-\mathrm{a} \cos 2 \pi \mathrm{x}+\mathrm{y}^2-\mathrm{a} \cos 2 \pi \mathrm{y}
f(x,y)=2a+x2−acos2πx+y2−acos2πy
import numpy as np
def fitness_func(X):
# 目标函数,即适应度值,X是种群的表现型
a = 10
pi = np.pi
x = X[:, 0]
y = X[:, 1]
return 2 * a + x ** 2 - a * np.cos(2 * pi * x) + y ** 2 - a * np.cos(2 * 3.14 * y)
def decode(x, a, b):
"""解码,即基因型到表现型"""
xt = 0
for i in range(len(x)):
xt = xt + x[i] * np.power(2, i)
return a + xt * (b - a) / (np.power(2, len(x)) - 1)
def decode_X(X: np.array):
"""对整个种群的基因解码,上面的decode是对某个染色体的某个变量进行解码"""
X2 = np.zeros((X.shape[0], 2))
for i in range(X.shape[0]):
xi = decode(X[i, :20], -5, 5)
yi = decode(X[i, 20:], -5, 5)
X2[i, :] = np.array([xi, yi])
return X2
def select(X, fitness):
"""根据轮盘赌法选择优秀个体"""
fitness = 1 / fitness # fitness越小表示越优秀,被选中的概率越大,做 1/fitness 处理
fitness = fitness / fitness.sum() # 归一化
idx = np.array(list(range(X.shape[0])))
X2_idx = np.random.choice(idx, size=X.shape[0], p=fitness) # 根据概率选择
X2 = X[X2_idx, :]
return X2
def crossover(X, c):
"""按顺序选择2个个体以概率c进行交叉操作"""
for i in range(0, X.shape[0], 2):
xa = X[i, :]
xb = X[i + 1, :]
for j in range(X.shape[1]):
# 产生0-1区间的均匀分布随机数,判断是否需要进行交叉替换
if np.random.rand() <= c:
xa[j], xb[j] = xb[j], xa[j]
X[i, :] = xa
X[i + 1, :] = xb
return X
def mutation(X, m):
"""变异操作"""
for i in range(X.shape[0]):
for j in range(X.shape[1]):
if np.random.rand() <= m:
X[i, j] = (X[i, j] + 1) % 2
return X
def ga():
"""遗传算法主函数"""
c = 0.3 # 交叉概率
m = 0.05 # 变异概率
best_fitness = [] # 记录每次迭代的效果
best_xy = []
iter_num = 100 # 最大迭代次数
X0 = np.random.randint(0, 2, (50, 40)) # 随机初始化种群,为50*40的0-1矩阵
for i in range(iter_num):
X1 = decode_X(X0) # 染色体解码
fitness = fitness_func(X1) # 计算个体适应度
X2 = select(X0, fitness) # 选择操作
X3 = crossover(X2, c) # 交叉操作
X4 = mutation(X3, m) # 变异操作
# 计算一轮迭代的效果
X5 = decode_X(X4)
fitness = fitness_func(X5)
best_fitness.append(fitness.min())
x, y = X5[fitness.argmin()]
best_xy.append((x, y))
X0 = X4
# 多次迭代后的最终效果
print("最优值是:%.5f" % best_fitness[-1])
print("最优解是:x=%.5f, y=%.5f" % best_xy[-1])
# 最优值是:0.00000
# 最优解是:x=0.00000, y=-0.00000
# 打印效果
ga()