zoukankan      html  css  js  c++  java
  • Needleman–Wunsch 算法的代码实现

    Needleman–Wunsch 算法的代码实现

    # -*- coding: utf-8 -*-
    """   
        :Author: huangsh
        :Date: 19-7-28 下午19:17
        :Description: 使用bidu Needleman–Wunsch 算法来计算两条序列的最大相似得分  
        如果您对此算法不熟悉,可以去看看我写的一篇拙文:https://www.jianshu.com/p/002bbebcaaef
    """
    
    from collections import namedtuple
    
    F = namedtuple('F', ('score', 'pointer'))
    
    ## 初始化二维矩阵, # 生成 x行,y列的二维矩阵,初始化第0行,0列的元素
    def init_array(x, y):  
        array = [[0] * (y) for _ in range(x)]
        array[0][0] = F(0, None)
        for j in range(1, y):
            array[0][j] = F((-5)*j, [0, j-1])
        for i in range(1, x):
            array[i][0] = F((-5)*i, [i-1, 0])
        return array
    
    ## 一行一行的计算矩阵中的每个各自中的最优结果。当前格子中的最优结果由它的三个来源推出
    def compute(array, seq1, seq2):
        row, col = len(seq2), len(seq1)
        for i in range(1, row+1):
            for j in range(1, col+1):
                if seq1[j-1] == seq2[i-1]:  # 这里简化了得分矩阵,完全匹配得10分,不完全得5分,有gap减5分
                    s = 10
                else:
                    s = 5  
                lu = [array[i-1][j-1].score+s, [i-1, j-1]] # idx 0:最大得分,idx 1:来源坐标
                left = [array[i-1][j].score-5, [i-1, j]]
                up = [array[i][j-1].score-5, [i, j-1]]
                max_choice = max([lu,left, up], key=lambda x: x[0])
                score= max_choice[0]
                pointer = max_choice[1]
                array[i][j] = F(score, pointer)  # 在当前保存最大得分,和来源坐标,方便回溯。
        return array
    
    ## 回溯。从(m,n)一直回溯到(0,0)
    def backtrack(array, seq1, seq2):
        s1 = []
        s2 = []
        row, col = len(seq2), len(seq1)
        while array[row][col].score != 0:
            i, j = array[row][col].pointer # pointer 指向来源方的坐标
            if i+1 == row and j+1 == col: # 左上方
                s1.append(seq1[col-1])
                s2.append(seq2[row-1])
                row, col = i, j
            elif row == i+1 and col == j: # 来源:上方
                s1.append("-")
                s2.append(seq2[i])
                row, col = i, j
            elif row == i and col == j+1: # 左方
                s1.append(seq1[j])
                s2.append("-")
                row, col = i, j
        s1 = ''.join(s1[::-1])  #因为是从最后往前回溯的,需要将逆转一下list
        s2 = ''.join(s2[::-1])
        return s1, s2
    
    def main(seq1, seq2):
        x, y = len(seq2)+1 , len(seq1)+1 # x是矩阵行数,y是矩阵列数
    
        array = init_array(x, y)
        array = compute(array, seq1, seq2)
        s1, s2 = backtrack(array, seq1, seq2)
        max_score = array[x-1][y-1].score
    
        print("最大得分:", max_score)
        print(s1)
        print(s2)
    
    if __name__ == '__main__':
        seq1 = "ATCGCGCAACTGCGCGC"
        seq2 = "ACGCGCACTGCGGC"
        main(seq1, seq2)
    
    
  • 相关阅读:
    CodeForces 1017B
    POJ 1323-Game Prediction(贪心)
    CodeForces 104B-Testing Pants for Sadness(思维题)
    CodeForces 1324D
    UVA 1152-4 Values whose Sum is 0(二分查找)
    POJ 1700-Crossing River(贪心)
    HDU 1789-Doing Homework again(并查集+贪心)
    SDUT 1298-活动选择(贪心)
    HDU 1272-小希的迷宫(带环并查集)
    CodeForces
  • 原文地址:https://www.cnblogs.com/huanping/p/11273391.html
Copyright © 2011-2022 走看看