遗传算法计算最值_20200513_

利用简单遗传算法计算函数的最值
作者:袁江磊

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
pd.set_option('display.max_rows', None)# 显示所有行

#表格创建
def pd_creat():
    na=[['na']*6]*number
    pd_all=pd.DataFrame(na,columns=['基因x','基因y','基因z','代数','适应度','适应度排名'])
    return pd_all

#初始化种群
def init_population():
    all_process = pd.DataFrame(['start'] * 6, columns=['start'], index=['基因x', '基因y', '基因z', '代数', '适应度',
                            '适应度排名']).T  # 整个进化过程[[[种群成员],[适应度]],[[种群成员],[适应度]],...]
    pd_all=pd_creat()
    all_process = all_process.append(pd_all)
    all_process['代数']=1
    all_process.drop('start',axis=0,inplace=True)
    for i in range(number):
        init_popula=np.random.randint(init_range[0], init_range[1], 3).tolist()
        all_process.ix[i,['基因x','基因y','基因z']]=init_popula
        all_process.ix[i, ['适应度']]=fitness(init_popula[0],init_popula[1],init_popula[2])
    all_process=all_process.sort_values(['适应度'])
    all_process['适应度排名']=range(1,number+1)
    return all_process

#计算种群适应性数值
def fitness( x, y, z):
    fit = (x-3.14)**2+3.7*np.cos(y-8.43)+(z-3.43)**2-54.3
    return fit

#生成新一代
def breed(genera,all_process):

    new_generation=pd_creat()#添加新一代扩展表
    last_generation = all_process.ix[all_process['代数']==genera-1]#上一代
    new_generation['代数']=genera

    last_generation.index=range(1,number+1)
    new_generation.index=range(1,number+1)

    #染色体两两交叉
    best_genera=last_generation.ix[last_generation['适应度排名']<=round(number*p_best)]
    for i in range(1,int(number/2)+1):
        first=last_generation.ix[2*i-1, ['基因x', '基因y', '基因z']]
        first['基因z']=last_generation.ix[2*i,['基因x', '基因y', '基因z']][2]

        second = last_generation.ix[2*i, ['基因x', '基因y', '基因z']]
        second['基因z'] = last_generation.ix[2*i-1, ['基因x', '基因y', '基因z']][2]

        #发生变异
        first[0]+=p_change*np.random.normal(0,1,1)[0]
        second[0] += p_change*np.random.normal(0,1,1)[0]

        first[1] += p_change*np.random.normal(0, 1, 1)[0]
        second[1] += p_change*np.random.normal(0, 1, 1)[0]

        first[2] += p_change*np.random.normal(0, 1, 1)[0]
        second[2] += p_change*np.random.normal(0, 1, 1)[0]

        new_generation.ix[2*i-1,['基因x', '基因y', '基因z']]=first
        new_generation.ix[2*i, ['基因x', '基因y', '基因z']] = second

    #计算刚交叉完后的新一代适应度集排名
    for i in range(1,number+1):
        init_popula=new_generation.ix[i,['基因x','基因y','基因z']]
        new_generation.ix[i, ['适应度']]=fitness(init_popula[0],init_popula[1],init_popula[2])
    new_generation = new_generation.sort_values(['适应度'])
    new_generation['适应度排名'] = range(1, number + 1)

   #将上一代最优质个体留下并加入新一代
    new_generation=new_generation.ix[new_generation['适应度排名']<=number-2]
    new_generation=new_generation.append(last_generation.ix[last_generation['适应度排名']<=2])
    new_generation.index=range(1,number+1)
    new_generation['代数'] = genera

    # 计算留下上一代最优质的数据后的新一代适应度集排名
    for i in range(1, number + 1):
        init_popula = new_generation.ix[i, ['基因x', '基因y', '基因z']]
        new_generation.ix[i, ['适应度']] = fitness(init_popula[0], init_popula[1], init_popula[2])
    new_generation = new_generation.sort_values(['适应度'])
    new_generation['适应度排名'] = range(1, number + 1)

    X=new_generation.ix[new_generation['适应度排名']==1]

    print('x'+str(X['基因x'].tolist()[0])+'y:'+str(X['基因y'].tolist()[0])+'z'+str(X['基因z'].tolist()[0])+'适应度:'+str(X['适应度'].tolist()[0]))
    all_process=all_process.append(new_generation)#将新一代添加至总表中
    return all_process

def main(last_genera,all_process):
    #迭代至第n代
    out_count = 0
    for genera in range(2,last_genera):

        all_process=breed(genera, all_process)
        print('已经生成'+str(genera)+'代,已经完成'+str(round(genera/last_genera,2)*100)+'%')

        last_fit = all_process.ix[all_process['适应度排名'] == 1]['适应度'].tolist()[-2]
        fit = all_process.ix[all_process['适应度排名'] == 1]['适应度'].tolist()[-1]

        # 衡量每次迭代最优适应度变化量,当变化量连续小于某个次数30时将终止迭代
        delt = (fit - last_fit) / last_fit
        if abs(delt) < p_out:
            out_count += 1
        if out_count > 30:
            break
        #print(out_count)
    return all_process

if __name__=='__main__':
    number = 14  # 种群数量
    p_best=1/4#留下上一代中最优比例
    p_change=0.2#变异程度
    p_out=0.0007#当每代最优值变化幅度小于此值时便会终止迭代
    init_range=[4,8]#初始种族数据范围
    all_process=pd_creat()
    all_process=init_population()#创建初始种群
    #向下迭代一百次
    all_process=main(1000,all_process)

    data_best=all_process.ix[all_process['适应度排名']==1]#查看排名第一的数值演变
    print(data_best)
    plt.plot(data_best['代数'],data_best['适应度'])
    plt.show()

    #print(all_process.ix[all_process['代数']<=20])



猜你喜欢

转载自blog.csdn.net/weixin_45590329/article/details/106107096
今日推荐