一、Needleman-Wunsch 算法

  尼德曼-翁施算法(英语:Needleman-Wunsch Algorithm)是基于生物信息学的知识来匹配蛋白序列或者DNA序列的算法。这是将动态算法应用于生物序列的比较的最早期的几个实例之一。该算法是由 Saul B. Needlman和 Christian D. Wunsch 两位科学家于1970年发明的。本算法高效地解决了如何将一个庞大的数学问题分解为一系列小问题,并且从一系列小问题的解决方法重建大问题的解决方法的过程。该算法也被称为优化匹配算法和整体序列比较法。时至今日尼德曼-翁施算法仍然被广泛应用于优化整体序列比较中。

二、初始化得分矩阵

  首先建立如下的得分矩阵。从第一列第一行的位置起始。计算过程从d 0,0开始,可以是按行计算,每行从左到右,也可以是按列计算,每列从上到下。当然,任何计算过程,只要满足在计算 d(i , j) 时 d (i-1, j)(上边)、d (i-1 , j-1) (左上)和 d(i, j-1) (左边)都已经被计算这个条件即可。在计算 d(i , j)后,需要保存d(i , j)是从 d (i-1 , j) 、d(i-1 , j-1) 或 d(i, j-1) 中的一个推进的,或保存计算的路径,以便于后续处理。上述计算过程到 d(m , n) 结束,其中m,n各位两个序列的长度。

      G C A T G C U
  0              
G                
A                
T                
T                
A                
C                
A                

三、选择得分体系

  我们可以看出每个位置配对都有三种可能情况:匹配, 不匹配与错位(或插入):

  • 匹配: 两个字母相同

  • 不匹配:两个字母不相同

  • 错位:一个字母与另一个序列中的间隔(空白)相匹配

  这三种得分情况有很多打分标准,这些情况都总结在得分体系的部分。从现在开始,我们将使用Needleman 和Wunsch创造的简单体系来进行打分,即匹配得1分,不匹配得-1分,错位得-1分.

四、填充评分矩阵

  开始于第二行中的第二列,初始值为0。通过矩阵一行一行移动,计算每个位置的分数。得分被计算为从现有的分数可能的最佳得分(即最高)的左侧,顶部或左上方(对角线)。当一个得分从顶部计算,或从左边这代表在我们的对准的插入缺失。当我们从对角线计算分数这表示两个字母所得位置匹配的对准。定不存在“向上”或“左上”的位置对第二行,我们只能从现有单元向左添加。因此,我们添加-1的权利,因为这代表了从以前的比分插入缺失。这导致在第一行是0,-1,-2,-3,-4,-5,-6,-7。这同样适用于第二列,因为我们只具有以上现有分数。因此,我们有:

    G C A T G C U
  0 -1 -2 -3 -4 -5 -6 -7
G -1              
A -2              
T -3              
T -4              
A -5              
C -6              
A -7              

  第一种情况是存在向三个方向构筑矩阵,周围位置得分如下:

    G
  0 -1
G -1 ?

  该单元格具有三个可能的候选总和:

  • 对角线的左上邻居的分数为0。G和G的配对是匹配项,因此添加匹配项的分数:0 + 1 = 1
  • 正上邻居的得分为-1,从那里移动代表一个indel,因此将indel的得分相加:(-1)+(-1)=(-2)
  • 左邻居的得分也为-1,代表插入缺失,也产生(-2)。

  得分最高的单元格也必须记录下来。在的文章最开始说的那矩阵图中,它表示为从行和列3中的单元格到行和列2中的单元格的箭头,?号处根据评分规则最后为1。

  对接下来的位置,我们有不同的选择。

    G C
  0 -1 -2
G -1 1 X
 A -2   Y  

  X:

  • 上: (-2)+(-1) = (-3)

  • 左: (+1)+(-1) = (0)

  • 左上: (-1)+(-1) = (-2)

  Y:

  • 上: (1)+(-1) = (0)

  • 左: (-2)+(-1) = (-3)

  • 左上: (-1)+(-1) = (-2)

  对于X和Y,最高得分均为0。
  两个或所有相邻小格可能会达到最高的候选分数:

  T G
T 1 1
A 0 X
  • Top: (1)+(-1) = (0)

  • Top-Left: (1)+(-1) = (0)

  • Left: (0)+(-1) = (-1)

  在这种情况下,必须将达到最高候选得分的所有方向记录为中并完成图中可能的起点,例如,在第7行和第7列的单元格中。

  以这种方式填写表格会给出分数或所有可能的比对候选,右下角单元格中的分数代表最佳比对的比对分数。

五、追溯本源

  按照箭头的方向标记从右下角的单元格到左上角的单元格的路径。从此路径开始,将按照以下规则构建序列:

  • 对角箭头表示匹配或不匹配,因此原始单元格的列字母和行字母将对齐。

  • 水平或垂直箭头表示插入/缺失。 水平箭头将使间隙(“-”)与行的字母(“侧边”序列)对齐,垂直箭头将使间隙与列的字母(“顶部”序列)对齐。

  • 如果有多个箭头可供选择,则它们表示路线的分支。 如果两个或多个分支都属于从右下角到左上角单元格的路径,则它们是同等可行的路线。 在这种情况下,请注意将路径作为单独的对齐候选。

  遵循这些规则,上图中的一个可能的对齐候选者的步骤为:

U → CU → GCU → -GCU → T-GCU → AT-GCU → CAT-GCU → GCAT-GCU
A → CA → ACA → TACA → TTACA → ATTACA → -ATTACA → G-ATTACA

(branch) → TGCU → ...
→ TACA → ...

六、评分系统

  最简单的计分方案只是为每个匹配,不匹配和插入缺失给出一个值。 上面的分步指南使用match = 1,mismatch = -1,indel = -1。 因此,对准分数越低,编辑距离越大,因为该计分系统需要较高的分数。 另一个计分系统可能是:

  • Match = 0

  • Indel = 1

  • Mismatch = 1

  对于此系统,对齐分数将代表两个字符串之间的编辑距离。 可以针对不同的情况设计不同的评分系统,例如,如果认为差距对您的对齐方式非常不利,则可以使用对差距进行严重惩罚的评分系统,例如:

  • Match = 0

  • Mismatch = 1

  • Indel = 10

七、Needleman–Wunsch算法代码

  计算评分矩阵,按行推进,根据左、上、左上计算的结果取最大的:

 1     /**
2 * 一种用于计算全局最大相似度矩阵的实用方法。
3 *
4 * @param sequence1 代表第一个氨基酸序列的字符串。
5 * @param sequence1 代表第二个氨基酸序列的字符串。
6 * @param matchScore 代表分配给比赛的分数的浮点数。
7 * @param mismatchScore 一个浮点数,代表分配给不匹配项的分数。
8 * @param indelScore 浮点数表示分配给插入和删除的分数。
9 */
10 public static float[][] computeMatrix(String sequence1, String sequence2, float matchScore, float mismatchScore, float indelScore) {
11 sequence1 = "-" + sequence1;
12 sequence2 = "-" + sequence2;
13
14 float[][] resultMatrix = new float[sequence1.length()][sequence2.length()];
15
16 for (int i = 0; i < sequence1.length(); i++) {
17 resultMatrix[i][0] = i * indelScore;
18 }
19 for (int j = 0; j < sequence2.length(); j++) {
20 resultMatrix[0][j] = resultMatrix[0][j] = j * indelScore;
21 }
22
23 for (int i = 1; i < sequence1.length(); i++) {
24 for (int j = 1; j < sequence2.length(); j++) {
25 resultMatrix[i][j] = Math.max(resultMatrix[i - 1][j] + indelScore,
26 Math.max(resultMatrix[i][j - 1] + indelScore, resultMatrix[i - 1][j - 1] +
27 (sequence1.charAt(i) == sequence2.charAt(j) ? matchScore : mismatchScore)));
28 }
29 }
30
31 return resultMatrix;
32 }

  根据评分矩阵来按最低顺序获得最佳对齐:

 1     /**
2 * 一种计算两个的最佳全局最低对齐序列的实用方法
3 *
4 * @param similarityMatrix 2维数组表示以前计算的全局最大相似度矩阵。
5 * @param sequence1 代表第一个氨基酸序列的字符串。
6 * @param sequence1 代表第二个氨基酸序列的字符串。
7 * @param matchScore 代表分配给匹配的分数的浮点数。
8 * @param mismatchScore 一个浮点数,代表分配给不匹配项的分数。
9 * @param indelScore 浮点数表示分配给插入和删除的分数。
10 */
11 public static OptimalAlignment obtainOptimalAlignmentByDownmostOrder(float similarityMatrix[][],
12 String sequence1, String sequence2, double matchScore, double mismatchScore, double indelScore) {
13
14 int i = similarityMatrix.length - 1;
15 int j = similarityMatrix[0].length - 1;
16 StringBuilder alignment1Builder = new StringBuilder();
17 StringBuilder alignment2Builder = new StringBuilder();
18
19 sequence1 = "-" + sequence1;
20 sequence2 = "-" + sequence2;
21
22 while (i != 0 && j != 0) {
23 if (similarityMatrix[i][j] == (similarityMatrix[i][j - 1] + indelScore)) {
24 alignment1Builder.insert(0, "-");
25 alignment2Builder.insert(0, sequence2.charAt(j));
26 j--;
27 } else if (similarityMatrix[i][j] == (similarityMatrix[i - 1][j - 1] + (sequence1.charAt(i) == sequence2.charAt(j) ? matchScore : mismatchScore))) {
28 alignment1Builder.insert(0, sequence1.charAt(i));
29 alignment2Builder.insert(0, sequence2.charAt(j));
30 i--;
31 j--;
32 } else if (similarityMatrix[i][j] == (similarityMatrix[i - 1][j] + indelScore)){
33 alignment1Builder.insert(0, sequence1.charAt(i));
34 alignment2Builder.insert(0, "-");
35 i--;
36 }
37 }
38
39 return new OptimalAlignment(alignment1Builder.toString(), alignment2Builder.toString());
40 }

  测试主函数:

 1   public static void main(String[] args) {
2 String sequence1 = "GCATGCU";
3 String sequence2 = "GATTACA";
4
5 float matchScore = 1;
6 float mismatchScore = -1;
7 float indelScore = -1;
8
9 float[][] computedMatrix = NeedlemanWunsch.computeMatrix(sequence1, sequence2, matchScore, mismatchScore, indelScore);
10
11 System.out.println("Best global downmost alignment: ");
12 System.out.println(NeedlemanWunsch.obtainOptimalAlignmentByDownmostOrder(computedMatrix, sequence1, sequence2, matchScore, mismatchScore, indelScore));
13 }

  全局相似度矩阵:

  结果:

字符串与模式匹配算法(六):Needleman–Wunsch算法的更多相关文章

  1. 常用算法3 - 字符串查找/模式匹配算法(BF & KMP算法)

    相信我们都有在linux下查找文本内容的经历,比如当我们使用vim查找文本文件中的某个字或者某段话时,Linux很快做出反应并给出相应结果,特别方便快捷! 那么,我们有木有想过linux是如何在浩如烟 ...

  2. 文本比较算法:Needleman/Wunsch算法

    本文介绍基于最长公共子序列的文本比较算法——Needleman/Wunsch算法.还是以实例说明:字符串A=kitten,字符串B=sitting那他们的最长公共子序列为ittn(注:最长公共子序列不 ...

  3. 文本比较算法Ⅱ——Needleman/Wunsch算法

    在"文本比较算法Ⅰ--LD算法"中介绍了基于编辑距离的文本比较算法--LD算法. 本文介绍基于最长公共子串的文本比较算法--Needleman/Wunsch算法. 还是以实例说明: ...

  4. 利用Needleman–Wunsch算法进行DNA序列全局比对

    生物信息学原理作业第二弹:利用Needleman–Wunsch算法进行DNA序列全局比对. 具体原理:https://en.wikipedia.org/wiki/Needleman%E2%80%93W ...

  5. 字符串的模式匹配算法——KMP模式匹配算法

    朴素的模式匹配算法(C++) 朴素的模式匹配算法,暴力,容易理解 #include<iostream> using namespace std; int main() { string m ...

  6. 字符串与模式匹配算法(二):MP算法

    一.MP算法介绍 MP 算法(Morris-Pratt算法)是一种快速串匹配算法,它是詹姆斯·莫里斯(James Morris)和沃恩·普莱特(Vaughan Pratt)在1970年提出的一种快速匹 ...

  7. 字符串与模式匹配算法(一):BF算法

    一.BF算法的基本思想 BF(Brute Force)算法是模式匹配中最简单.最直观的算法.该算法最基本的思想是从主串的第 start 个字符起和模式P(要检索的子串)的第1个字符比较,如果相等,则逐 ...

  8. 字符串与模式匹配算法(四):BM算法

    一.BM算法介绍 BM算法(Boyer-Moore算法)是罗伯特·波义尔(Robert Boyer)和杰·摩尔(J·Moore)在1977年共同提出的.与KMP算法不同的是,BM算法是模式串P由左向右 ...

  9. 字符串与模式匹配算法(三):KMP算法

    一.KMP算法介绍 KMP算法与前面的MP算法一脉相承,都是充分利用先前匹配的过程中已经得到的结果来避免频繁回溯.回顾一下MP算法,如下图的模式串偏移,当前模式字符串P的左端的p0与目标字符串T中tj ...

随机推荐

  1. Python国内镜像源及报错解决方法

    国内镜像源: 阿里云:https://mirrors.aliyun.com/pypi/simple/ 清华:https://pypi.tuna.tsinghua.edu.cn/simple/ 中国科技 ...

  2. 浅谈 Xamarin Community Toolkit 的未来发展

    .NET MAUI会在今年晚些时候发布,我们也很高兴和大家一起分享我们对Xamarin Community Toolkit的计划! 这包括 .NET MAUI Community Toolkit.Xa ...

  3. 【noip1998】题解:2的幂次方

    思路:设递归函数dfs(x)用于输出x的幂次方 最容易的思路:0不输出,1输出为2(0),2输出2,剩下的递归执行. 每一次递归:例如7,拆分为4+3,先拆出最大的是2的次方的数出来,输出4,再把3分 ...

  4. Linux没有/var/log/messages日志文件

    1.新安装的CentOS8没有/var/log/messages日志文件: 安装rsyslog: dnf  install   -y  rsyslog 或 yum  install  -y  rsys ...

  5. 【OI】蛇形填数题的深入探究

    题目:在 n×n 方阵里填入 1,2,...n×n, 要求蛇形填数.例如,n=4 时方阵为: 10  11  12  1 9    16  13  2 8    15  14  3 7     6  ...

  6. CSS写一个缺角的div和菱形

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  7. 初探DispatcherServlet#doDispatch

    初探DispatcherServlet#doDispatch 写在前面 SpringBoot其实就是SpringMVC的简化版本,对于request的处理流程大致是一样的, 都要经过Dispatche ...

  8. pycharm向GitHub提交代码

    设置为自动add commit代码 push代码 查看github,看到提交记录

  9. P5074-Eat the Trees【插头dp】

    正题 题目链接:https://www.luogu.com.cn/problem/P5074 题目大意 给出一个\(n\times m\)的网格,有的必须铺线有的不能,铺成若干条闭合回路,求方案数. ...

  10. P4357-[CQOI2016]K远点对【K-Dtree】

    正题 题目链接:https://www.luogu.com.cn/problem/P4357 题目大意 平面上给出\(n\)个点,求第\(k\)远的点对距离. 解题思路 \(\text{K-Dtree ...