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

遗传算法实现引物设计(Python语言)

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

遗传算法实现引物设计(Python语言)

文章来源:

          doi:10.1093/bioinformatics/bth147  

          “Primer design using genetic algorithm”

一、背景&问题

        什么是引物设计,引物设计很重要,是PCR实验(聚合酶链式反应,是一种让DNA序列以指数方式快速扩增的实验)的前置动作,引物的质量好坏影响PCR实验的成功与否。迄今为止,已经开发了许多基于经典算法的引物设计方法。

        在进行聚合酶链式反应实验之前,需要一对引物来剪切目标DNA子序列。然而,这是一项繁琐的任务,因为需要满足太多的约束。已经提出了各种设计引物的方法,但是它们中的大多数在设计的引物上没有限制性位点,并且不满足特异性限制。

二、解决方案

        在给定的模板序列里,生成种群进行引物对的随机搜索,并计算对应的适应度,选择拥有优秀适应度的作为子代,模拟染色体的交叉、变异过程。待迭代次数足够且种群结果收敛后,得到最优的引物对结果,该引物对具有特异性和限制性位点。

三、总流程

模板:TP53基因的CDS部分区域,长度为587

产物长度:80~150

交叉概率:0.6

变异概率:0.1

(一)初始化种群

初始化过程随机产生群体P的初始个体,群体P有N个解Pt,一个解对应一对引物,解Pt被定义为向量:Pt=(Fs,Fe,Rs,Re)。但由于四个组成部分是依赖的(其中一个在交叉或变异过程中被改变,有时可能导致引物或产物违反长度约束)。

为了避免这个问题,将依赖性质转化为独立的形式,Pt=(Fs,α,β,γ)。其中α=Fe-Fs, β=Rs-Fe, γ=Re-Rs。

Fs:上游引物的起始位点,0≤Fs≤模板长度-最小产物长度

α:上游引物长度,18≤α≤26

β:上游引物结束位点与下游引物起始位点之间的距离,最小产物长度-α-γ≤β≤最大产物长度-α-γ   and      Fs+α+β+γ≤模板长度

γ:下游引物长度,18≤γ≤26

 (二)适应度函数&选择

适应度函数:

子函数满足要求置0,不满足要求置1

leng:长度(18~26)

lengd:长度差(≤3)

Tmd:Tm差(≤5)

퐺퐶푝:GC含量(0.4~0.6)

Term:引物3’末端是否为G或C

Uni:引物特异性(每条引物与模板序列之间只有一处退火位置)

Sc:引物不能有自身互补序列,否则产生发夹结构

 PC:一个引物不应与另一个引物互补配对,否则产生引物二聚体

 푅푡:是否有限制性位点,进行模式匹配,验证酶是否在其上。其中模式匹配长度:                                                ​​​​​​​        ​​​​​​​        ​​​​​​​        ​​​​​​​        

文章所使用的限制性酶及其核酸序列:

选择:

         对计算完适应度值的引物组进行筛选,其fitness越低,引物越符合要求。取fitness的倒数,将反比例关系转成正比例关系后,进行筛选(轮盘赌)。

         每个引物对被选择作为下一代的机率:

                ​​​​​​​        ​​​​​​​        ​​​​​​​        ​         ​​​​​​

(三)交叉&变异

交叉:

        产生小于16的十进制随机数,转成四位二进制数后,将位数为1的位置进行互换,得到新的引物对。对新得到的引物对Pt=(Fs,α,β,γ)进行检查,若同时满足产物长度合理和下游引物结束位点不越界,则进入下一步;否则重新开始交叉过程。

eg:

变异:

        随机改变四个部分中的一个,按照初始化时的变量范围来赋值,然后检查变异后的个体是否符合约束。检查的方式同上。

eg:

 流程图:

 四、运行结果

有提前出现适应度最优的引物即fitness=0的情况,且解有时不唯一,如下图所示(很可能是设定的产物长度明显小于模板长度的缘故)

 五、代码核心部分

fitness函数:

def each_fitness(pt):#适应度函数
    return leng(pt)+3*lengd(pt)+3*Tmd(pt)+3*GCp(pt)+3*Term(pt)+50*Uni(pt)+10*Sc(pt)+10*PC(pt)+Rt(pt)

def leng(pt):#长度限制
    if 18<=len(Bf(pt)) <= 26 and 18 <= len(Br(pt)) <= 26:
        return 0
    else:
        return 1

def lengd(pt):#长度差限制
    if abs(len(Bf(pt))-len(Br(pt)))<=3:
        return 0
    else:
        return 1

def Tmd(pt):#Tm差限制
    if abs(Tm(Bf(pt))-Tm(Br(pt)))<=5:
        return 0
    else:
        return 1

def GCp(pt):#GC含量限制
    if 0.4 <= GC(Bf(pt)) <= 0.6 and 0.4 <= GC(Br(pt)) <= 0.6:
        return 0
    else:
        return 1

def Term(pt):#两引物3'末端情况
    return Termf(pt)+Termr(pt)

def Termf(pt):#上游引物3'末端情况
    f3=pt[0]+pt[1]-1
    if GDC[f3] == 'g' or GDC[f3] == 'c':
        return 0
    else:
        return 1

def Termr(pt):#下游引物3'末端情况
    r3=pt[0]+pt[1]+pt[2]
    if GD[r3] == 'g' or GD[r3] == 'c':
        return 0
    else:
        return 1

def Uni(pt):#两引物特异性情况
    return Unif(pt)+Unir(pt)

def Unif(pt):#上游引物特异性情况(模式匹配和GDC)
    if GDC.count(Bf(pt)) == 1:
        return 0
    else:
        return 1

def Unir(pt):#下游引物特异性情况(模式匹配和GD)
    if GD.count(Br(pt)) == 1:
        return 0
    else:
        return 1

def Sc(pt):#自互补
    tempf=0
    tempr=0
    #上游引物情况
    for i in range(0, len(Bf(pt))):
        strf = Bf(pt)[i:i + 4]
        if Bf(pt).find(reverse(complete(strf)),i+4)!=-1:#这里的4可以调,以调整发夹不配对圈的大小
            tempf=1
            break
    #下游引物情况
    for i in range(0, len(Bf(pt))):
        strr = Br(pt)[i:i + 4]
        if Bf(pt).find(reverse(complete(strr)),i+4)!=-1:#这里的4可以调,以调整发夹不配对圈的大小
            tempr=1
            break
    if tempf==0 and tempr==0:
        return 0
    else:
        return 1

def PC(pt):#间互补
    if getNumofCommonSubstr(Bf(pt),complete(Br(pt))) <= 3 and getNumofCommonSubstr(Bf(pt),reverse(complete(Br(pt)))) <= 3:
        return 0
    else:
        return 1

def Rt(pt):#搜索限制位点
    temp=1
    # 上游引物限制位点
    for i in similar_list:
        if Bf(pt).count(i)!=0:
            temp=0
            break
    # 下游引物限制位点
    for i in similar_list:
        if reverse(Bf(pt)).count(i)!=0:
            temp=0
            break
    if temp==0:
        return 0
    else:
        return 1

def get_fitness(mat):#获得种群适应度值清单
    fitness=np.zeros((pop_size,1))
    for i in range(pop_size):
        #print(mat[i])
        fitness[i]=each_fitness(mat[i])

    return fitness

初始化种群:

def init_mat():#初始化种群
    mat=np.zeros((pop_size,vector_size))
    for i in range(0,pop_size):
        #初始化生成vector
        Fs=np.random.randint(0,template_length-min_length+1)
        alpha=np.random.randint(18,27)
        gamma=np.random.randint(18,27)
        if max_length-alpha-gamma+1 

选择:

def select(pop, profitness):#选择最优(根据fitness的倒数)

    idx = np.random.choice(np.arange(pop_size), size=pop_size, replace=True,
                           p=(profitness) / (profitness.sum()))

    better_pop = pop[idx]
    return better_pop

交叉&变异:

def crossover_and_mutation(pop):
    new_pop = []
    for father in pop:  # 遍历种群中的每一个个体,将该个体作为父亲
    #    print(type(father))     ndarray
    #    print(father.shape)     (48,)
        child = father  # 孩子先得到父亲的全部基因(这里我把一串二进制串的那些0,1称为基因)

        # 产生子代时不是必然发生交叉,而是以一定的概率发生交叉 0~Pe
        if np.random.rand() < Pe:
            child=crossover(child,pop)
        # 每个后代有一定的机率发生变异,以一定的概率发生变异 0~Pm
        if np.random.rand() < Pm:
            child = mutation(child)
        new_pop.append(child)
    return new_pop          #list类型

def crossover(child,pop):
    while True:
        mother = pop[np.random.randint(pop_size)]  # 再种群中选择另一个个体,并将该个体作为母亲,类型与father一样
        seq=bina(np.random.randint(0,16))
        for i in range(4):
            if seq[i]==1:
                temp=child[i]
                child[i]=mother[i]
                mother[i]=temp
        if 80<=child[1]+child[2]+child[3]<=150 and child[0]+child[1]+child[2]+child[3]<=template_length:
            break
    return child

def mutation(child):
    while True:
        index=np.random.randint(0,4)
        if index==0:
            child[0]=np.random.randint(0,template_length-min_length+1)
        if index==1:
            child[1]=np.random.randint(18,27)
        if index==2:
            if max_length - child[1] - child[3] + 1 < template_length - child[0] - child[1] - child[3] + 1:
                beta = np.random.randint(min_length - child[1] - child[3], max_length - child[1] - child[3] + 1)
            else:
                beta = np.random.randint(min_length - child[1] - child[3], template_length - child[0] - child[1] - child[3] + 1)
        if index==3:
            child[3]=np.random.randint(18,27)
        if 80<=child[1]+child[2]+child[3]<=150 and child[0]+child[1]+child[2]+child[3]<=template_length:
            break
    return child
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/925551.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

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

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