python实现遗传算法求解函数最大值

人工智能小作业,仅记录

简单概念介绍:

进化算法(evolutionary algorithms,EA)是以达尔文的进 化论思想为基础,通过模拟生物进化过程和机制来求解问题的 自组织、自适应的人工智能技术,是借鉴生物界自然选择和自 然遗传机制的一种随机搜索算法。进化算法主要通过选择、交叉(重组)和变异这三 种操作,用于处理传统搜索方法难以解决的复杂的 和非线性的优化问题。

python实现遗传算法求解函数最大值_第1张图片

摘自ppt

 函数:y=10sin(5x)+7|x-5|+10

流程:

随机编码,x∈[0,10],精度10-4,通过计算可知216<105<217,故一个点的编码需要17位的二进制串。

通过随机数来决定每位编号,再进行种群初始化,每代个体固定个数,再将二进制数转化为十进制数,再计算函数值。

计算每个个体(每个点)的适应度,因为要求函数最大值,此处的适应度函数直接采用所给函数,函数值越大,被选择的概率最大。

通过随机抽选来决定保留哪些个体,并对剩余的个体进行交叉(此处采用的是二进制串的单点交叉),此外可选择一定几率的变异(即随机某些位数取反)。

在进化代数达到一定程度时(此处默认generation=100,可更改),输出数据可视化结果,并标出最大值(绿色的是当前代中的最大值,红色的是函数中的最大值)。

所以所有功能函数可切割为:编码,二进制转十进制,计算函数值,选择并保留个体,交配并存入文件,变异,结果输出。

代码分析:(注释见代码中)

import matplotlib.pyplot as plt
import numpy
import random

def f(x):#进行函数计算
    y=10*numpy.sin(5*x)+7*abs(x-5)+10
    return y

def encode(bi_individuals):#初代进行编码
    for i in range(10):
        bi_individual=[]#单个二进制串
        for j in range(17):
            bi_individual.append(random.randint(0,100)%2)#0,1随机
        bi_individuals.append(bi_individual)
    return bi_individuals

def decode(bi_individuals,de_individuals):#解码(二进制->十进制)并计算函数值
    de_individuals.clear()
    for i in range(10):
        sum=0
        de_individual=[0,0]
        for j in range(1,18):
            sum+=pow(2,j-1)*bi_individuals[i][-j]
        de_individual[0]=sum*10/(pow(2,17)-1)
        de_individual[1]=f(de_individual[0])#函数计算
        de_individuals.append(de_individual)

def choose(de_individuals,bi_individuals):#计算被选择的概率,并进行选择
    p=[0]*10
    sum_f=0
    for de_individual in de_individuals:
        sum_f+=de_individual[1]
    for i in range(10):
        p[i]=de_individuals[i][1]/sum_f
    new_de_individuals=random.choices(de_individuals,p,k=10)#用函数按照概率随机抽取
    new_bi_individuals=[]
    for i in range(10):
        ind=de_individuals.index(new_de_individuals[i])
        new_bi_individuals.append(bi_individuals[ind])#找到所选个体对应的二进制串
    return new_de_individuals,new_bi_individuals

def cross(bi_individuals):
    n=random.randint(1,5)#随机有几对进行交叉,此处范围为[1,5]
    list=[x for x in range(10)]
    for i in range(n):
        a=random.choice(list)
        list.remove(a)
        b=random.choice(list)
        list.remove(b)#交叉的个体不会重复交叉
        dir=random.randint(1,16)
        new1=bi_individuals[a][0:dir]+bi_individuals[b][dir:]
        new2=bi_individuals[b][0:dir]+bi_individuals[a][dir:]
        bi_individuals[a]=new1
        bi_individuals[b]=new2
    return bi_individuals

def vary(bi_individuals,vary_or_not):#进行变异操作
    for i in range(10):
        if vary_or_not[i]:
            dir1=random.randint(0,16)
            dir2=random.randint(0,16)
            bi_individuals[i][dir1]=(bi_individuals[i][dir1]+1)%2
            bi_individuals[i][dir2]=(bi_individuals[i][dir2]+1)%2

def show_result(de_individuals):#结果展示
    max_xs=[]
    max_y=0
    for de_individual in de_individuals:
        if de_individual[1]>max_y:
            max_y=de_individual[1]
            max_xs.clear()
            max_xs.append(de_individual[0])
        elif de_individual[1]==max_y:
            max_xs.append(de_individual[0])#筛选出最后一代中的最大值,如果有两个不同点y值相同,则全部记录
    x=numpy.arange(0,10,0.02)
    y=10*numpy.sin(5*x)+7*abs(x-5)+10
    plt.plot(x,y)#画出总函数图
    for i in x:
        if 10*numpy.sin(5*i)+7*abs(i-5)+10==max(y):
            whole_max_x=i#整个函数范围内的最大值
    plt.plot(whole_max_x,max(y),marker='o',color='red')#标记最大值
    for max_x in max_xs:
        plt.plot(max_x,max_y,marker='^',color='green')#标记最后一代的最大值,由此可看出遗传算法所得最大值和实际最大值相差多少
    plt.title("y=10sin(5x)+7|x-5|+10")
    plt.xlabel("x∈[0,10]")
    plt.ylabel("y")
    plt.show()

def heredity(generation=50):#遗传算法总的执行函数
    t=0
    bi_individuals=[]#二进制编码存放处
    de_individuals=[]#对应十进制数据&函数值存放处
    bi_individuals=encode(bi_individuals)#编码
    proba=[0.97,0.03]#此处设定变异几率为3%
    flag=[0,1]#判断是否发生变异
    while t

生成图像:

python实现遗传算法求解函数最大值_第2张图片 

generation=50,n=10

python实现遗传算法求解函数最大值_第3张图片 

generation=50,n=100

 python实现遗传算法求解函数最大值_第4张图片generation=100,n=10

 python实现遗传算法求解函数最大值_第5张图片

generation=100,n=100 

你可能感兴趣的:(python)