一种优化的Genetic Algorithm —— Python实现

来源:互联网 发布:面相分析软件 编辑:程序博客网 时间:2024/06/05 07:13

一种优化的Genetic Algorithm —— Python实现


优化内容:

1、 加入精英保护机制,种群内最优秀个体将被保留,精英更迭采用“打擂机制”,加快收敛。

2、 变异基因数服从泊松分布,模拟每个基因在同一时刻具有相同变异几率,接近实际。

3、 为获得更清晰的数学特性,增强对变异的可控性,不再使用常规GA的基因编码方式实现难以用数学概率描述的变异。

4、 指定变异造成的变化量与变异基因数目成指数关系(源代码采用2的幂级数),模拟自然界的基因变异影响,使得陷入局部最优的可能性下降,同时保证算法的搜索精度极高。

5、 加入适应度对变异率的影响,模仿自然界中,适应度越高的个体类型竞争压力越小,基因频率发生改变的概率越小。越不适应环境的个体相应的变异率会大大提升,变异的大小也因此增大。实验发现,这项优化减小了最优解附近的搜索步长,对减少最优解附近的振荡有非常明显的作用。

6、 适应度函数加入平方项,使得优劣个体差异增大,选择强度增大,加快收敛。实验发现,达到相同收敛程度的迭代次数至少减少了50%。

7、 在每一季度(每一次迭代更新一代)加入外来种群,采用在可行域均匀分布的随机生成,模拟外来个体的竞争压力,实验表明对防止陷入局部解有很明显的作用。

源代码:

# -*- coding: utf-8 -*-# 遗传算法优化from math import sin as sinfrom math import cos as cosfrom math import exp as expfrom random import random as randfrom random import shuffle as shufflefrom copy import copyrg = [[-2.25, 2.5], [-2.5, 1.75]]  # 搜索范围ST = 25  # 约束条件N = 300  # 初始种群规模E = 0.05  # 适应度偏移修正e = 0.01  # 变异基础值T = 4  # 淘汰比率/每个个体平均产生配子数n = 2  # 输入变量数/染色体数/修改这里以实现不同的模型# g = 1000     # 输入空间分割数/决定单个性状的基因数(线性变异用)g1 = 20  # 输入空间分割数/决定单个性状的基因数e1 = 0.30  # 基础变异比率times = 80  # 迭代次数/引入平方项后收敛速度很快psw = 0.5  # 交换发生概率T = T / 2  # 淘汰比率修正# 目标函数/修改这里以实现不同的模型def y(x):    return sin(x[1]) * exp(1 - cos(x[0])) ** 2 + cos(x[0]) * exp(1 - sin(x[1])) ** 2 + (x[0] - x[1]) ** 2# 约束函数/修改这里以实现不同的模型def st(x):    if (x[0] + 5) ** 2 + (x[1] + 5) ** 2 < ST:        return True    return False# 生成初始种群def initiate():    M = [[0.0 for j in range(n)] for i in range(N)]    num = 0    while num < N:        m = [rand() * (j[1] - j[0]) + j[0] for j in rg]        if st(m):            M[num] = m            num = num + 1    return M# 评估适应度def fitting(Y):    y_max = max(Y)    f = [(y_max - yi) ** 2 + E for yi in Y]    return [j / sum(f) for j in f]# 产生配合子,注:使用乘法修正概率密度函数远快于遍历一个向量def reproduction(F, M):    P = []    for i in range(N):        for j in range(F[i]):            P.append(M[i])    return P# 变异处理,F为配合子数目向量,生成一个变异矩阵(线性变异,已经停用,可用于对照组)def mutate(F, Y):    y_min = min(Y)    pe = [(y_min - yi) ** 2 + e for yi in Y]    pe = [j / sum(pe) for j in pe]  # 对优等个体进行保护,利用二次项减少变异概率    mutt = []    for i in range(N):        for j in range(F[i]):            mt = [poisson(pe[i] * g) * (round(rand() - 0.001) * 2 - 1) * (rg[k][1] - rg[k][0]) / g for k in range(n)]            mutt.append(mt)    return mutt# 变异处理,F为配合子数目向量,生成一个变异矩阵(2-指数变异)def mutate1(F, Y):    y_min = min(Y)    pe = [(y_min - yi) ** 2 + e for yi in Y]    pe = [j * N * e1 / (sum(pe)) for j in pe]  # 对优等个体进行保护,利用二次项减少变异概率    mutt = []    for i in range(N):        for j in range(F[i]):            mt = [(2 ** poisson(pe[i] * g1)) * (round(rand() - 0.001) * 2 - 1) * (rg[k][1] - rg[k][0]) / (2 ** g1) for k                  in range(n)]            mutt.append(mt)    return mutt# 生成泊松分布随机数,方法:Knuth方法,拟合二项分布对变异数目进行估计,期望lambda = npdef poisson(l):    L = float(exp(-l))    k = 0.0    p = 1.0    while 1:        k = k + 1        p = p * rand()        if p < L:            break    return k - 1# 交叉互换def switch(P, Pi):    sw = [int(rand() <= psw) for t in range(n)]    for i in range(len(P)):        for j in range(n):            temp = P[i][j]            P[i][j] = Pi[i][j] * sw[j] + P[i][j] * (1 - sw[j])            Pi[i][j] = temp * sw[j] + Pi[i][j] * (1 - sw[j])    return P + Pi# GA主函数def genetic_algorithm():    M = initiate()  # 随机生成初始种群    elite = M[0]  # 精英初始化    my = y(elite)  # 精英适应度初始化    for t in range(times):        Y = [y(m) for m in M]  # 表现型/输出        f = fitting(Y)  # 适应度        if min(Y) < my:  # 精英竞争            my = min(Y)            idx = Y.index(my)            elite = M[idx]  # 精英个体保护        F = [int(round(j * T * N)) for j in f]  # 个体生成配合子个数/繁殖次数        P = reproduction(F, M)  # 生成繁殖序列        mutt = mutate1(F, Y)  # 变异矩阵        P = map(lambda (a, b): map(lambda (l1, l2): l1 + l2, zip(a, b)), zip(P, mutt))  # 执行变异        i = 0      # 个体可行性检查/可行域检查        while i < len(P):            if ~st(P[i]):                P.pop(i)            i = i + 1        Pi = copy(P)        shuffle(P)  # 打乱组合1        shuffle(Pi)  # 打乱组合2        Mi = switch(P, Pi) + initiate()  # 进入种群的外来个体        Mi.append(elite)  # 精英保留于种群        Yi = [y(m) for m in Mi]        fi = fitting(Yi)        M = []        c = 0        while c < N:     # 从子代优选个体成为新一代父代            ym = max(fi)            idx = fi.index(ym)            fi[idx] = 0            if st(Mi[idx]):                M.append(Mi[idx])                c = c + 1    Y = [y(m) for m in M]  # 表现型/输出    f = fitting(Y)  # 适应度    ym = max(f)    idx = f.index(ym)    return M[idx], Y[idx]M, Y = genetic_algorithm()print M, Y

结论:

采用Wikipedia标准优化测试数据

优化函数为:
这里写图片描述
图像为:
这里写图片描述

运行结果:

这里写图片描述

结果为:
迭代次数:79
初始种群规模:300
运行时间:2.419秒
最优解:x = -3.1228519294852823, y = -1.589523976110672
最小值:-106.787733679

对比标准参考解:
这里写图片描述

可以发现此优化算法在短时间内获得了比标准参考更优的结果,足以证明此算法具有可行性。

原创粉丝点击