栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

进化算法(GA)Python实现--以ackley函数为例

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

进化算法(GA)Python实现--以ackley函数为例

前言

        有关进化算法的介绍可以查看进化算法框架的介绍及Matlab实现(遗传算法)里面的算法介绍,这里使用Python重新实现一次。

        此内容只测试ackley函数,如果需要测试其他函数,可以在Hedar test set中的测试函数这个链接中查看函数,可以下载MATLAB的函数实现代码参考,之后也用Python重写。

1. 测试函数 1.1 ackley函数介绍

 

 1.2 ackley函数-Python计算
# ackley函数
def ackley(x):
    n = 2
    a = 20; b = 0.2; c = 2*np.pi
    s1 = 0
    s2 = 0
    for i in range(0,n):
       s1 = s1+x[i]**2
       s2 = s2+math.cos(c*x[i])
    y = -a*math.exp(-b*math.sqrt(1/n*s1))-math.exp(1/n*s2)+a+math.exp(1)
    return y
1.2 ackley函数的三维图形-Python画图

记得ackley函数也要放进去,这里的内容就不重复所以没放

import matplotlib.pyplot as plt
import numpy as np


def printAckley():
    
    x = np.arange(-30,30,0.1)
    y = np.arange(-30,30,0.1)
    x,y = np.meshgrid(x,y)
    z = np.zeros((x.shape[0],y.shape[1]),dtype=float)
    for i in range(0,x.shape[0]):
        for j in range(0,y.shape[1]):
            z[i,j] = ackley([x[i,j],y[i,j]])
    fig = plt.figure()
    ax = fig.add_subplot(111,projection='3d')
    ax.plot_surface(x,y,z)
    plt.show()

if __name__ == '__main__':
    printAckley()
2. GA的主要模块

导入的模块

import numpy as np
import math
dt = np.dtype(np.float64) # 定义np数组的数据类型,方便统一修改
2.1 初始化种群

在指定的范围的内随机生成种群

'''
 初始化种群大小
    种群大小popsize:设置种群大小
    维度dim:个体的维度
    取值范围bounds:每个个体每一维的取值范围
'''
def initPop(pop_size,dim,bounds):
    pop = np.random.rand(pop_size,dim)
    for i in range(0,dim):
        pop[:,i] = pop[:,i]*(bounds[i,1]-bounds[i,0])+bounds[i,0]
    return pop
2.2 计算种群的函数值
'''
种群计算,计算ackley函数,可以改为其他,ackley函数改一下即可
    种群pop:传入种群矩阵(数组)
    种群函数值pop_value:返回计算结果
'''
def calAckleyPop(pop):
    pop_x = pop.shape[0]
    pop_value = np.zeros((pop_x,1),dtype=dt)

    for i in range(0,pop_x):
        pop_value[i,0] = ackley(pop[i,:])
    return pop_value
2.3 计算种群的适应值

做计算得到的种群函数值做归一化处理。不一定需要做这一步,可以直接以函数值作为种群的适应值,但是到迭代后期,由于整个种群可能都趋近0,函数值作为适应值不好作为比较。

# 计算种群适应值,值进行归一化处理,,有些父代选择方式需要先做归一化处理
def calFitvalue(pop_value):
    value = 1/(pop_value+0.001) #防止分母为0,加上0.001
    max_value = max(value)
    min_value = min(value)
    fitvalue = (value-min_value)/(max_value-min_value+0.001) # 防止最大和最小是同一个值
    return fitvalue
2.4 选择父代个体

这里的父代选择方式比较简单,直接选择最佳的前N个。

# 父代选择函数,直接取前80%的个体作为父代
def selectParent(pop,fitvalue):
    # 对fitvalue进行排序,获取索引值
    fit_index = np.argsort(fitvalue,axis=0)
    fit_index = fit_index[::-1]
    pop_x,pop_y = pop.shape
    parent_num = int(pop_x//1.2)
    new_pop = np.zeros((parent_num,pop_y),dtype=dt)
    for i in  range(0,parent_num):
        new_pop[i,:] = pop[fit_index[i],:]
    return new_pop
2.5 杂交操作
# 杂交操作
def crossover(pop,pc):
    pop_x,pop_y = pop.shape
    child_pop = np.zeros((2,pop_y),dtype=dt)
    new_pop = np.zeros((1,pop_y),dtype=dt)
    for i in range(0,pop_x):
        if np.random.rand() 
2.6 变异操作 
# 变异操作
def mutation(pop,pm,bounds):
    pop_x,pop_y = pop.shape
    new_pop = np.zeros((1,pop_y),dtype=dt)
    for i in range(0,pop_x):
         # 个体变异概率
        if np.random.rand() 
2.7 种群更新操作 
def updataPop(pop,pop_size,fitvalue):
    pop_x,pop_y = pop.shape
    if pop_x <= pop_size:
        return pop
    new_pop = np.zeros((pop_size,pop_y),dtype=dt)
    new_fitvalue = np.zeros((pop_size,1),dtype=dt)
    fit_index = np.argsort(fitvalue,axis=0)
    fit_index = fit_index[::-1]

    for i in range(0,pop_size):
        new_pop[i,:] = pop[fit_index[i],:]
        new_fitvalue[i,:] = fitvalue[fit_index[i],:]

    return new_pop,new_fitvalue
2.8 获取最佳个体
def bestFit(pop,fitvalue):
    fit_index = np.argsort(fitvalue,axis=0)
    fit_index = fit_index[::-1]
    best_one = pop[fit_index[-1]]
    best_fit = calAckleyPop(best_one)
    return best_one,best_fit
3. 测试结果 3.1 测试函数
def main():
    pop_size = 200
    dim = 20
    bounds = np.ones((dim,2),dtype=int)
    bounds[:,0] = -15
    bounds[:,1] = 30
    #print(bounds)
    pc = 0.8
    pm = 0.3

    pop = initPop(pop_size,dim,bounds)
    pop_value = calAckleyPop(pop)
    fitvalue = calFitvalue(pop_value)
    #print(fitvalue)
    
    for i in range(0,100):  
        perant_pop = selectParent(pop,fitvalue) # 选择父代
        pop_c = crossover(perant_pop,pc)        # 杂交操作
        new_pop = np.concatenate((pop_c,pop))   # 合并种群和杂交获得的后代pop_c得到新种群
        pop_m = mutation(new_pop,pm,bounds)     # 新种群做变异操作,得到变异种群pop_c
        new_pop = np.concatenate((pop_m,new_pop)) # 合并pop_c新种群
        
        new_pop_value = calAckleyPop(new_pop)   # 计算新种群的函数值
        fitvalue = calFitvalue(new_pop_value)   # 计算种群适应值
        pop,fitvalue= updataPop(new_pop,pop_size,fitvalue) # 更新种群
        
    best_one,best_fit = bestFit(pop,fitvalue)
    print(best_fit[0,0])

if __name__ == '__main__':
    for i in range(0,20):
        main()
3.2 结果

4.440892098500626e-16 这个值在Python中好像就是最低值,对这个没有去追究。Python数据精度相关的知识了解并不多。正在学习中,内容仅作为参考。

 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/998426.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号