The algorithm of Gotoh
In the last article, I introduced the sequence alignment problem. What I did not tell you is that it is practically useless for any real-world application. Oops, I am sorry about that!
But don’t be upset, reading it was not a complete waste of your precious time: The algorithm of Gotoh I am going to present here is much easier to comprehend when you have a good knowledge about Needleman-Wunsch, and what you can do with Gotoh indeed is highly relevant in many applications.
Why are fixed gap costs way too simple?
Remember our example alignment?
WTHGQACVELSIW
|||. .|.|
WTHA-----VSLW
Using the BLOSUM50 matrix and gap costs of , this alignment has a score of 40.9. Unfortunately, there is another alignment with a score of 45.9:
WTHGQACVELSIW
||| | | |.|
WTH--A-V--SLW
Naturally, this alignment has a better score, as it only has a single mismatch as compared to three. In fact, it is the optimal alignment for these two sequences and this scoring system (BLOSUM50 and ).
But remember what I told you about the importance of a meaningful alignment? Substitutions between glycine and alanine, leucine and valine or leucine and isoleucine occur frequently due to their biochemical similarities. Apart from that, there is only a single insertion or deletion (of five amino acids) in the first alignment. In the second, there are three insertions or deletions (of two, one and two amino acids, respectively). Judge for yourself, which alignment is more meaningful? Of course, noone can really know about the true evolutionary history of these two sequences (I am sure about that, because it was me who invented these two as an example for this blog), but in general, fewer gaps, even if they are long, should be preferred over many short gaps.
Unfortunately, using fixed gap costs does not allow us to model the length of gaps: Each gap by itself costs a fixed penalty, independent of other adjacent gaps. Thus, we have to adapt our scoring system accordingly: Instead of fixed gap costs, we now introduce a gap cost function , which maps the natural number to a gap penalty.
Of note, the aforementioned fixed gap costs correspond to a linear gap cost function without intercept term:
But let us now try a different class of functions for , for instance the affine function and see what happens: The total gap cost for the first alignment is . For the second alignment . Thus, the total score of the first alignment becomes 30.9, the total score of the second 15.9. In fact, the first alignment is optimal, and this is exactly what we wanted.
Thus, using an affine function can help to make the optimal alignments more meaningful. Of note, the parameters and are often called gap open and gap extension costs for obvious reasons. Be careful, when defined in a straight-forward way as the parameters of an affine function, for a gap of length 1, gap open and gap extension must be paid. This is a bit counterintuitive so many people use a different definition (such that a gap of length 1 only costs one gap open, of length 2 a gap open and a gap extension and so on). Of course, both definitions are equivalent, but when specifying parameters, always make sure that you know which definition has been used.
Dynamic programming for sequence alignment with arbitrary gap cost functions
Can we still use our good old Needleman-Wunsch implementation to optimize alignments with any gap cost function? Unfortunatly, the answer is no, as the following example shows:
Remember our three cases for the dynamic programming algorithm with fixed gap costs (a.k.a. linear gap cost function)? Case (b) looked like that:
………….. | |
………….. | - |
With linear gap costs, if the optimal alignment of prefixes and looks like that, then the alignment part without the last column (the dotted part) also is an optimal alignment (for and $$t^j$). For other gap cost functions, this does not hold anymore:
Consider the optimal alignment of AILW
and AL
with :
AILW
AL--
As the similarity score of I and L is not much worse than the score for L and L, the affine gap cost function prefers one gap of length two over two gaps of length one. This alignment corresponds to case (b), however, the alignment
AIL
AL-
obviously is not optimal. Oh no! Do we have to start over and come up with something completely new? Luckily that’s not the case: What leads to problems here is a long trailing gap in case (b) or (c). Therefore, we have to distinguish again three cases to derive how to compute : (a) the optimal alignment of and ends with a match/mismatch, (b) the optimal alignment ends with a gap of length k in , or (c) the optimal alignment ends with a gap of length k in . Note that this is very similar to the derivation for linear gap cost functions, we only consider the trailing gap length and introduce an open variable k.
Again, in all three cases, there is a prefix alignment that is optimal. For (a), it is the alignment without the last column, which can be proven as for linear gap costs. For (b) (and, equivalently, for (c)), the optimal alignment has the form:
………….. | x | … | ||
………….. | - | … | - |
x is either a gap or . The alignment left of (and including) x and (let’s call it P) is optimal under all alignments ending with (i.e. not having a gap in the last column in ).
Prove: Assume that it is not optimal. Then there is an alignment Q of and with a better score than P but still ending with . Replacing P by Q in the alignment above would result in a better score for and , contradicting our assumption.
Note that considering here as the alignment column before the trailing gaps in is crucial, as this ensures that there is no trailing gap in the shorter alignment (also see the counter-example above). By the character , we ensure that the scores of the prefix alignment (either P or Q) and the trailing gap can be summed for a total alignment score.
Unfortunately, this makes things a bit more complicated, as we do not know k. We only know that, if (b) is the case, one of the scores in through plus the corresponding costs for the trailing gap leads to an optimal alignment for and . Thus, to compute we now have to consider much more entries than before:
For convenience, we factorized the maximum into the three cases (a), (b) and (c). In tabular form:
A | … | … | |||||
… | … | ||||||
… | |||||||
… | |||||||
I.e. we have to maximize over the whole column above the entry (and add, to each entry, the respective gap costs) and the whole row left if the entry. This increases the runtime to and is known as the algorithm of Waterman, Smith and Beyer.
The algorithm of Gotoh for affine gap cost functions
Remember that in contrast to the linear gap cost function , more general gap cost functions can produce more meaningful optimal alignments. However, these better alignments come with the cost of an often prohibitive cubic runtime.
However, can we do better when we restrict ourselves to the affine gap cost function ? Let’s see:
We start by inserting that into the the definition of $I$ and factorize:
Adjusting the index and factoring out an from the maximum, this becomes
What does that mean? If, in addition to we also tabulate and , we can compute each and value in constant time! So, our overall runtime again is , we only have to take care of three matrices instead of one during dynamic programming. I called them and , as their scores correspond to the optimal alignments that end with a gap in (deletion) or in (insertion), respectively.
This is called the algorithm of Gotoh.
Gotoh in a nutshell
First, all three matrices are initialized:
For convenience, the undefined values and are set to infinity (They are undefined, as there is no alignment with an empty string that ends with gap in ): To compute $I_{1,1}$, for instance, the formula is . As , this undefined value will not be used and no special case must be introduced.
Second, fill the three matrices systematically with the recurrences:
This can be done again e.g. row-by-row, always computing , then and then and then proceeding to the next entry. The optimal alignment score can again be found in .
Third, the optimal alignment itself can be computed using backtracking. Importantly, in a canonical implementation, not only the two coordinates must be tracked, but also in which matrix the current backtracking step is taking place. This always was the greatest cause for programming errors in our practical course, so we came up with a more clever backtracking scheme (see the next post for that; o yes, this is just a perfect cliffhanger…)
One important thing to consider is the following: What to do, if the maximum is not unique, so there are two (or more) possible ways for backtracking. The answer is clear: It does not matter, both alignments have the same optimal score!
Additional remarks
Of course, all variants for special treatment of leading and trailing gaps (including local alignments) can also be computed with the algorithm of Gotoh (you just need to use the Waterman trick in ).
Of note, for concave gap cost functions, there is an algorithm with runtime .