GA算法的简单实现

ZeroDesigner [DrugDesign](javascript:void(0);) 前天

好久没有更新了,我也是佛系小编。

话不多说,直接上CODE。

目标函数:y=sin(x),求最大值

算法:基因遗传算法

语言:Python

思路:

使用二进制代表十进制,类似于使用[100100,111100]代表十进制的[36,60]

染色体交叉为:设置随机数,单点交叉如[101100,110100],这就是上面两个染色体单点交叉的结果,第二个数字起

突变:0变为1,1变为0

选择下一代:轮盘赌,哪个个体适应度函数高,被选择的机会就更大

image

# -*-coding:utf-8 -*-
#求解sin(x)最大值
import random
import math
import matplotlib.pyplot as plt
from interval import Interval
import numpy as np
import itertools
#初始化生成chromosome_length大小的population_size个个体的二进制基因型种群
#本质为创造一个列表,其中嵌套列表
#species_origin_np,species_origin_list功能一样
#下面是创造种群的两种方式一种是使用np一种是使用list
def species_origin_np(population_size,chromosome_length):
    population=[list(np.random.choice(['0','1'],chromosome_length, p=[0.5,0.5])) for i in range(population_size)]
    return population
def species_origin_list(population_size,chromosome_length):
    #第一个列表代表种群列表
    population=[]
    #二维列表,包含染色体和基因
    for i in range(population_size):
        #这个列表代表染色体
        temporary=[]
        #染色体暂存器
        for j in range(chromosome_length):
            temporary.append(str(random.randint(0,1)))
            #随机产生一个染色体,由二进制数组成
        population.append(temporary)
            #将染色体添加到种群中
            #最后返回的是种群
    return population
    
    #将基因拼接起来
    #产生一串二进制数字
def bin(chromosome_list:'list'):
    tmp=''.join(chromosome_list)
    return int(tmp)


    #从二进制到十进制
def translation(population:'list'):
    tmp=[int(str(i),2) for i in population]
    return tmp


    # 目标函数相当于环境 对染色体进行筛选,这里是sin(x)
def function(population:'list',max_value:'int'):
    chromosome_length=len(population[0])
    population=[bin(i) for i in population]
    # 暂存种群中的所有的染色体(十进制)
    temporary=translation(population)
    #一个基因代表一个决策变量,其算法是先转化成十进制,然后再除以2的基因个数次方减1(固定值)。
    tmp_x=[temporary[i]*max_value/(math.pow(2,chromosome_length)-1) for i in range(len(temporary))]
    function_list=[math.sin(x) for x in tmp_x]
    #类似于标准化的流程
    #这里将sin(x)作为目标函数,也是适应度函数
    return function_list    
    
def fitness(function_list): 
    fitness_list=[num if num >= 0 else 0 for num in function_list]
    # 如果适应度小于0,则定为0
    #将适应度添加到列表中
    sum=np.sum(np.array(fitness_list))
    #计算适应度和
    #计算概率
    pro_list=list(map(lambda x: x/sum, fitness_list))
    #计算累积概率
    cum_pro_list=[np.sum(np.array(pro_list[:i+1])) if i > 0 else pro_list[i] for i in range(len(pro_list))]
    #建立区间,下开上闭
    tmp_len=len(cum_pro_list) - 1
    interval_list=[Interval(cum_pro_list[i],cum_pro_list[i+1],upper_closed=True,lower_closed=False) for i in range(tmp_len)]
    interval_list.insert(0,Interval(0,cum_pro_list[0],upper_closed=True,lower_closed=False))
    return fitness_list,interval_list,pro_list
    
    #俄罗斯大轮盘,hahahahahhahh
def roulette(population,interval_list):
    new_population=[]
    #创建一个长度与population的随机列表,元素在(0,1)之间
    dec_pro=list(np.random.random(len(population)))
    #检查随机列表元素所在区间,然后,按照区间选取元素
    for x in range(len(dec_pro)):
        for y in range(len(interval_list)):
            if dec_pro[x] in interval_list[y]:
                new_population.append(population[y])
    return new_population
    #如果一个列表为嵌套列表
    #那么将其展开为一个列表
    #例如:
    # l1=[[1,2],[3,4]]
    # l2=[1,2,3,4]
def to_sim_list(more_list):
    new_list =[] 
    for x in range(len(more_list)):
        for y in range(len(more_list[x])):
            new_list.append(more_list[x][y])
    return new_list
            
    #单点交叉
def crossover(new_population):
    #列表任取两个元素形成新的列表
    tmp_population = list(itertools.combinations(new_population, 2))
    #产生交叉点的随机列表
    tmp_point=[random.randint(0,len(new_population[0])) for i in range(len(tmp_population))]
    #切片交叉
    for i in range(len(tmp_population)):
        tmp_population[i][0][tmp_point[i]:-1],tmp_population[i][1][tmp_point[i]:-1]=tmp_population[i][1][tmp_point[i]:-1],tmp_population[i][0][tmp_point[i]:-1]
    #列表展开
    cross_list = tmp_population = to_sim_list(tmp_population)
    #下面这个可能会报错
    #cross_list =[list(i) for i in list(np.unique(np.array(tmp_population),axis=0))]
    return cross_list
    #变异
    
    
def mutation(cross_list,pm,population_size):
    # 染色体/个体中基因的个数
    for x in range(len(cross_list)):
        for y in range(len(cross_list[0])):
            if random.random()<pm:
                # 如果小于阈值就变异  
                # 生成0到py-1的随机数
                if(cross_list[x][y]=='1'):
                    # 将基因进行单点随机变异,变为0或者1
                    cross_list[x][y]=='0'
                else:
                    cross_list[x][y]=='1'
    #将列表转化为矩阵,然后去重
    cross_list = [list(i) for i in list(np.unique(np.array(cross_list),axis=0))]
    #从列表cross_list中任意选取种群数量大小的元素
    new_population_list=np.random.randint(len(cross_list),size=population_size)
    mutation_list=[cross_list[i] for i in new_population_list]
    new_population=mutation_list
 #  new_population = list(random.sample(mutation_list, 20))
    return new_population
    #迭代
if __name__ == '__main__':
    population=species_origin_np(20,20)
    for i in range(100):
        function_list = function(population,2)
        fitness_list,interval_list,pro_list=fitness(function_list)
        print('This a '+ str(i) +' time:')
        sum=np.sum(np.array(fitness_list))
        print('Score:',sum/20)
        new_population=roulette(population,interval_list)
        cross_list=crossover(new_population)
        new_population=mutation(cross_list,0.01,20)
        population=new_population
    print('done')

看下结果:

image

个人公众号DrugDesign:

image
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343

推荐阅读更多精彩内容