{"componentChunkName":"component---src-templates-blog-template-js","path":"/blog/lazy-dynamic-programming","result":{"data":{"markdownRemark":{"html":"<p>I recently stumbled upon the edit distance problem again while working on an <a href=\"https://www.elastic.co/\">ElasticSearch</a> problem. It reminded me of the wonder and joy of studying algorithms. However well-trodden a path, another clever \"trick\" lies waiting to be found. Using the power of lazy evaluation to solve the edit distance problem is a beautiful rendition of an old favourite, yet current problem.</p>\n<p>Github repository with tests <a href=\"https://github.com/asherLZR/lazy-dynamic-programming\">here</a>. The following code samples are provided in Python where applicable and Haskell to demonstrate the constrast between the imperative and functional solutions. We will discuss 3 solutions including brute-force O(3<sup>N</sup>), standard dynamic programming O(|A| * |B|), and lazy dynamic programming O(|A| * (1 + D A B)).</p>\n<p><em>Based on the <a href=\"http://users.monash.edu/~lloyd/tildeStrings/Alignment/92.IPL.html\">paper</a> Lazy Dynamic-Programming Can be Eager by Dr. L. Allison (1992).</em></p>\n<h2>The Problem</h2>\n<p>Given 2 strings A and B, find the Levenshtein distance, the minimum number of point-mutations (delete, insert, substitutions) required to transform them into identical strings.</p>\n<p>For example, the word pair (\"cgggtatccaa\", \"ccctaggtccca\") has an edit distance of 6</p>\n<table>\n<thead>\n<tr>\n<th align=\"center\">Edit</th>\n<th align=\"center\">i</th>\n<th align=\"center\">Diff</th>\n<th align=\"center\">Result</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td align=\"center\">/</td>\n<td align=\"center\">/</td>\n<td align=\"center\">/</td>\n<td align=\"center\">\"cgggtatccaa\"</td>\n</tr>\n<tr>\n<td align=\"center\">DEL</td>\n<td align=\"center\">1</td>\n<td align=\"center\">g</td>\n<td align=\"center\">\"cggtatccaa\"</td>\n</tr>\n<tr>\n<td align=\"center\">SUB</td>\n<td align=\"center\">1</td>\n<td align=\"center\">g -> c</td>\n<td align=\"center\">\"ccgtatccaa\"</td>\n</tr>\n<tr>\n<td align=\"center\">SUB</td>\n<td align=\"center\">2</td>\n<td align=\"center\">g -> c</td>\n<td align=\"center\">\"ccctatccaa\"</td>\n</tr>\n<tr>\n<td align=\"center\">INS</td>\n<td align=\"center\">5</td>\n<td align=\"center\">g</td>\n<td align=\"center\">\"ccctagtccaa\"</td>\n</tr>\n<tr>\n<td align=\"center\">INS</td>\n<td align=\"center\">6</td>\n<td align=\"center\">g</td>\n<td align=\"center\">\"ccctaggtccaa\"</td>\n</tr>\n<tr>\n<td align=\"center\">SUB</td>\n<td align=\"center\">10</td>\n<td align=\"center\">a -> c</td>\n<td align=\"center\">\"ccctaggtccca\"</td>\n</tr>\n</tbody>\n</table>\n<p>Note that there may be multiple sets of point-mutations that arrive at the same solution.</p>\n<p>The edit distance problem is useful in a variety of applications including DNA sequencing, spell-check, and spam filtering.</p>\n<h2>Subproblems</h2>\n<p>The solution to this problem comes from the insight that the cost of mutating a string can be minimised by taking the fewest mutations required for <code class=\"language-text\">a[:1], a[:2]..,a</code>. Note that a similar principle applies if we check from the last character of the string <code class=\"language-text\">a[-1], a[-2:].., a</code>.</p>\n<p>To take the example above, (\"cgggtatccaa\", \"ccctaggtccca\"), if we start from the last character of either string, conversion of (<code class=\"language-text\">a[-1]</code>, <code class=\"language-text\">b[-1]</code>), (\"a\", \"a\") requires a cost of 0. Then looking at  (<code class=\"language-text\">a[-2:]</code>, <code class=\"language-text\">b[-2:]</code>), (\"aa\", \"ca\"), the cost relies on the cost of the previous comparison, (\"a\", \"a\") and potential additions or deletions (\"\", \"a\"), (\"a\", \"\"). The last 2 are our base cases at cost 1.</p>\n<p>From this insight, we derive the following:</p>\n<p>The cost of converting substrings of a to b to each other is not incremented if the characters being examined match. In all other cases, a point-mutation is required so 1 is added to the minimum of 3 costs.</p>\n<h2>Naive Solution: O(3<sup>N</sup>)</h2>\n<p><em>where N = min(|A|, |B|).</em></p>\n<p>By checking all possible mutations recursively, we can incrementally build to the solution for the entire string. So far nothing special between either implementations.</p>\n<h3>Python Implementation</h3>\n<div class=\"gatsby-highlight\" data-language=\"py\"><pre class=\"language-py\"><code class=\"language-py\"><span class=\"token keyword\">def</span> <span class=\"token function\">edit_distance_rec</span><span class=\"token punctuation\">(</span>a<span class=\"token punctuation\">,</span> b<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    <span class=\"token keyword\">if</span> <span class=\"token builtin\">len</span><span class=\"token punctuation\">(</span>a<span class=\"token punctuation\">)</span> <span class=\"token operator\">==</span> <span class=\"token number\">0</span><span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">return</span> <span class=\"token builtin\">len</span><span class=\"token punctuation\">(</span>b<span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">if</span> <span class=\"token builtin\">len</span><span class=\"token punctuation\">(</span>b<span class=\"token punctuation\">)</span> <span class=\"token operator\">==</span> <span class=\"token number\">0</span><span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">return</span> <span class=\"token builtin\">len</span><span class=\"token punctuation\">(</span>a<span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">if</span> a<span class=\"token punctuation\">[</span><span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> b<span class=\"token punctuation\">[</span><span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">return</span> edit_distance_rec<span class=\"token punctuation\">(</span>a<span class=\"token punctuation\">[</span><span class=\"token punctuation\">:</span><span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> b<span class=\"token punctuation\">[</span><span class=\"token punctuation\">:</span><span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">else</span><span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">return</span> <span class=\"token number\">1</span> <span class=\"token operator\">+</span> <span class=\"token builtin\">min</span><span class=\"token punctuation\">(</span>edit_distance_rec<span class=\"token punctuation\">(</span>a<span class=\"token punctuation\">[</span><span class=\"token punctuation\">:</span><span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> b<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n                       edit_distance_rec<span class=\"token punctuation\">(</span>a<span class=\"token punctuation\">,</span> b<span class=\"token punctuation\">[</span><span class=\"token punctuation\">:</span><span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n                       edit_distance_rec<span class=\"token punctuation\">(</span>a<span class=\"token punctuation\">[</span><span class=\"token punctuation\">:</span><span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> b<span class=\"token punctuation\">[</span><span class=\"token punctuation\">:</span><span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></code></pre></div>\n<h3>Haskell Implementation</h3>\n<div class=\"gatsby-highlight\" data-language=\"hs\"><pre class=\"language-hs\"><code class=\"language-hs\"><span class=\"token hvariable\">recursiveEd</span> <span class=\"token operator\">::</span> <span class=\"token constant\">String</span> <span class=\"token operator\">-></span> <span class=\"token constant\">String</span> <span class=\"token operator\">-></span> <span class=\"token constant\">Int</span>\n<span class=\"token hvariable\">recursiveEd</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> <span class=\"token hvariable\">b</span> <span class=\"token operator\">=</span> <span class=\"token builtin\">length</span> <span class=\"token hvariable\">b</span>\n<span class=\"token hvariable\">recursiveEd</span> <span class=\"token hvariable\">a</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token builtin\">length</span> <span class=\"token hvariable\">a</span>\n<span class=\"token hvariable\">recursiveEd</span> <span class=\"token hvariable\">a</span><span class=\"token operator\">@</span><span class=\"token punctuation\">(</span><span class=\"token hvariable\">ax</span><span class=\"token operator\">:</span> <span class=\"token hvariable\">axs</span><span class=\"token punctuation\">)</span> <span class=\"token hvariable\">b</span><span class=\"token operator\">@</span><span class=\"token punctuation\">(</span><span class=\"token hvariable\">bx</span><span class=\"token operator\">:</span> <span class=\"token hvariable\">bxs</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">if</span> <span class=\"token hvariable\">ax</span> <span class=\"token operator\">==</span> <span class=\"token hvariable\">bx</span> <span class=\"token keyword\">then</span> <span class=\"token hvariable\">recursiveEd</span> <span class=\"token hvariable\">axs</span> <span class=\"token hvariable\">bxs</span>\n                        <span class=\"token keyword\">else</span> <span class=\"token number\">1</span> <span class=\"token operator\">+</span> <span class=\"token builtin\">minimum</span> <span class=\"token punctuation\">[</span><span class=\"token hvariable\">recursiveEd</span> <span class=\"token hvariable\">axs</span> <span class=\"token hvariable\">bxs</span><span class=\"token punctuation\">,</span> <span class=\"token hvariable\">recursiveEd</span> <span class=\"token hvariable\">axs</span> <span class=\"token hvariable\">b</span><span class=\"token punctuation\">,</span> <span class=\"token hvariable\">recursiveEd</span> <span class=\"token hvariable\">a</span> <span class=\"token hvariable\">bxs</span><span class=\"token punctuation\">]</span></code></pre></div>\n<h2>Tabular Dynamic Programming (O(|A| * |B|))</h2>\n<p>The previous solution works but is slow as there are recurring sub-problems that are not exploited. Dynamic programming is typically used to cache these previous edit values to avoid re-computation.</p>\n<h3>Python Implementation</h3>\n<div class=\"gatsby-highlight\" data-language=\"py\"><pre class=\"language-py\"><code class=\"language-py\"><span class=\"token keyword\">def</span> <span class=\"token function\">edit_distance</span><span class=\"token punctuation\">(</span>a<span class=\"token punctuation\">,</span> b<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n    memo <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">*</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">len</span><span class=\"token punctuation\">(</span>a<span class=\"token punctuation\">)</span><span class=\"token operator\">+</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">for</span> _ <span class=\"token keyword\">in</span> <span class=\"token builtin\">range</span><span class=\"token punctuation\">(</span><span class=\"token builtin\">len</span><span class=\"token punctuation\">(</span>b<span class=\"token punctuation\">)</span><span class=\"token operator\">+</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">]</span>\n    memo<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>x <span class=\"token keyword\">for</span> x <span class=\"token keyword\">in</span> <span class=\"token builtin\">range</span><span class=\"token punctuation\">(</span><span class=\"token builtin\">len</span><span class=\"token punctuation\">(</span>a<span class=\"token punctuation\">)</span><span class=\"token operator\">+</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">]</span>\n    <span class=\"token keyword\">for</span> i<span class=\"token punctuation\">,</span> row <span class=\"token keyword\">in</span> <span class=\"token builtin\">enumerate</span><span class=\"token punctuation\">(</span>memo<span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n        row<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> i\n    <span class=\"token keyword\">for</span> i <span class=\"token keyword\">in</span> <span class=\"token builtin\">range</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token builtin\">len</span><span class=\"token punctuation\">(</span>b<span class=\"token punctuation\">)</span><span class=\"token operator\">+</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n        <span class=\"token keyword\">for</span> j <span class=\"token keyword\">in</span> <span class=\"token builtin\">range</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token builtin\">len</span><span class=\"token punctuation\">(</span>a<span class=\"token punctuation\">)</span><span class=\"token operator\">+</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">:</span>\n            <span class=\"token keyword\">if</span> b<span class=\"token punctuation\">[</span>i<span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">==</span> a<span class=\"token punctuation\">[</span>j<span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">:</span>\n                memo<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>j<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> memo<span class=\"token punctuation\">[</span>i<span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>j<span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span>\n            <span class=\"token keyword\">else</span><span class=\"token punctuation\">:</span>\n                memo<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>j<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token builtin\">min</span><span class=\"token punctuation\">(</span>memo<span class=\"token punctuation\">[</span>i<span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>j<span class=\"token punctuation\">]</span><span class=\"token operator\">+</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> memo<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>j<span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token operator\">+</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> memo<span class=\"token punctuation\">[</span>i<span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span>j<span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token operator\">+</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">return</span> memo<span class=\"token punctuation\">[</span><span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">[</span><span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> memo</code></pre></div>\n<h3>Haskell Implementation</h3>\n<p>DP in a functional language with immutable variables utilises the caching property of unevaluated values, <a href=\"https://wiki.haskell.org/Thunk\">thunks</a> in Haskell. Each row is built recursively by taking as input the previous row, the row count, and character being compared.</p>\n<p>An in-depth explanation of how DP problems are solved in Haskell can be found <a href=\"http://travis.athougies.net/posts/2018-05-05-dynamic-programming-is-recursion.html\">here</a>.</p>\n<p>This is a copy of the implementation provided in the <a href=\"http://users.monash.edu/~lloyd/tildeStrings/Alignment/92.IPL.html\">paper</a>, translated to Haskell and commented.</p>\n<div class=\"gatsby-highlight\" data-language=\"hs\"><pre class=\"language-hs\"><code class=\"language-hs\"><span class=\"token comment\">-- | Solve the edit distance problem</span>\n<span class=\"token hvariable\">dynProgEd</span> <span class=\"token operator\">::</span> \n    <span class=\"token constant\">String</span>      <span class=\"token comment\">-- | first string a</span>\n    <span class=\"token operator\">-></span> <span class=\"token constant\">String</span>   <span class=\"token comment\">-- | second string b</span>\n    <span class=\"token operator\">-></span> <span class=\"token constant\">Int</span>      <span class=\"token comment\">-- | output to our edit distance problem</span>\n<span class=\"token hvariable\">dynProgEd</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> <span class=\"token hvariable\">b</span> <span class=\"token operator\">=</span> <span class=\"token builtin\">length</span> <span class=\"token hvariable\">b</span>\n<span class=\"token hvariable\">dynProgEd</span> <span class=\"token hvariable\">a</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token builtin\">length</span> <span class=\"token hvariable\">a</span>\n<span class=\"token hvariable\">dynProgEd</span> <span class=\"token hvariable\">a</span> <span class=\"token hvariable\">b</span> <span class=\"token operator\">=</span> \n    <span class=\"token keyword\">let</span> \n        <span class=\"token comment\">-- | Calculate all subsequent rows from the previous of the memoisation table</span>\n        <span class=\"token hvariable\">nextRows</span> <span class=\"token operator\">::</span> \n            <span class=\"token punctuation\">[</span><span class=\"token constant\">Int</span><span class=\"token punctuation\">]</span>       <span class=\"token comment\">-- | the previous row in the memoisation table</span>\n            <span class=\"token operator\">-></span> <span class=\"token punctuation\">[</span><span class=\"token constant\">Char</span><span class=\"token punctuation\">]</span>   <span class=\"token comment\">-- | the remaining characters of string a to be compared</span>\n            <span class=\"token operator\">-></span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">[</span><span class=\"token constant\">Int</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span>  <span class=\"token comment\">-- | subsequent rows of the memoisation table</span>\n        <span class=\"token hvariable\">nextRows</span> <span class=\"token hvariable\">_</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span>\n        <span class=\"token hvariable\">nextRows</span> <span class=\"token hvariable\">prevRow</span> <span class=\"token punctuation\">(</span><span class=\"token hvariable\">ax</span><span class=\"token operator\">:</span><span class=\"token hvariable\">axs</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=</span> \n            <span class=\"token keyword\">let</span> \n                <span class=\"token comment\">-- | Calculates the rest of the row from the previous character in the row</span>\n                <span class=\"token hvariable\">doRow</span> <span class=\"token operator\">::</span> \n                    <span class=\"token punctuation\">[</span><span class=\"token constant\">Char</span><span class=\"token punctuation\">]</span>      <span class=\"token comment\">-- | the remaining characters of string b to be compared</span>\n                    <span class=\"token operator\">-></span> <span class=\"token punctuation\">[</span><span class=\"token constant\">Int</span><span class=\"token punctuation\">]</span>    <span class=\"token comment\">-- | the previous row of the memoisation table starting from the column being examined</span>\n                    <span class=\"token operator\">-></span> <span class=\"token constant\">Int</span>      <span class=\"token comment\">-- | the previous cost assignment west of the current square</span>\n                    <span class=\"token operator\">-></span> <span class=\"token punctuation\">[</span><span class=\"token constant\">Int</span><span class=\"token punctuation\">]</span>    <span class=\"token comment\">-- | the rest of the row, cost of the remaining characters of string b</span>\n                <span class=\"token hvariable\">doRow</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> <span class=\"token hvariable\">_</span> <span class=\"token hvariable\">_</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span>\n                <span class=\"token hvariable\">doRow</span> <span class=\"token punctuation\">(</span><span class=\"token hvariable\">bx</span><span class=\"token operator\">:</span><span class=\"token hvariable\">bxs</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">(</span><span class=\"token hvariable\">nw</span><span class=\"token operator\">:</span><span class=\"token hvariable\">n</span><span class=\"token punctuation\">)</span> <span class=\"token hvariable\">w</span> <span class=\"token operator\">=</span>\n                    <span class=\"token keyword\">let</span> <span class=\"token hvariable\">me</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">if</span> <span class=\"token hvariable\">ax</span> <span class=\"token operator\">==</span> <span class=\"token hvariable\">bx</span> <span class=\"token keyword\">then</span> <span class=\"token hvariable\">nw</span> \n                        <span class=\"token keyword\">else</span> <span class=\"token number\">1</span> <span class=\"token operator\">+</span> <span class=\"token builtin\">minimum</span> <span class=\"token punctuation\">[</span><span class=\"token hvariable\">w</span><span class=\"token punctuation\">,</span> <span class=\"token hvariable\">nw</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">head</span> <span class=\"token hvariable\">n</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">]</span>\n                    <span class=\"token keyword\">in</span> <span class=\"token hvariable\">me</span><span class=\"token operator\">:</span><span class=\"token hvariable\">doRow</span> <span class=\"token hvariable\">bxs</span> <span class=\"token hvariable\">n</span> <span class=\"token hvariable\">me</span>\n                <span class=\"token hvariable\">firstElement</span> <span class=\"token operator\">=</span> <span class=\"token number\">1</span> <span class=\"token operator\">+</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">head</span> <span class=\"token hvariable\">prevRow</span><span class=\"token punctuation\">)</span>\n                <span class=\"token hvariable\">thisRow</span> <span class=\"token operator\">=</span> <span class=\"token hvariable\">firstElement</span><span class=\"token operator\">:</span><span class=\"token punctuation\">(</span><span class=\"token hvariable\">doRow</span> <span class=\"token hvariable\">b</span> <span class=\"token hvariable\">prevRow</span> <span class=\"token hvariable\">firstElement</span><span class=\"token punctuation\">)</span>\n            <span class=\"token keyword\">in</span> <span class=\"token hvariable\">thisRow</span><span class=\"token operator\">:</span><span class=\"token hvariable\">nextRows</span> <span class=\"token hvariable\">thisRow</span> <span class=\"token hvariable\">axs</span>\n        <span class=\"token hvariable\">table</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token operator\">..</span><span class=\"token builtin\">length</span> <span class=\"token hvariable\">b</span><span class=\"token punctuation\">]</span><span class=\"token operator\">:</span><span class=\"token hvariable\">nextRows</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">head</span> <span class=\"token hvariable\">table</span><span class=\"token punctuation\">)</span> <span class=\"token hvariable\">a</span>\n    <span class=\"token keyword\">in</span> <span class=\"token builtin\">last</span> <span class=\"token operator\">$</span> <span class=\"token builtin\">last</span> <span class=\"token hvariable\">table</span></code></pre></div>\n<h2>Lazy Dynamic Programming O(|A| * (1 + D A B))</h2>\n<h3>Haskell Implementation</h3>\n<p>In the previous solutions, we built a memoisation table to calculate our edit distance values. However this is inefficient because the only value that matters is the one in the last position of some diagonal in <code class=\"language-text\">table</code>! This means that the number of intermediate calculations to get to that value can be minimised. How do we use laziness to do this? We will go through 3 general ideas then let the code speak about its specifics; they are:</p>\n<ol>\n<li>Prefer diagonals over rows to enforce order of evaluation</li>\n<li>Force evaluation in a consistent direction</li>\n<li>Be lazy - declare calculation of new values based on un-evaluated dependencies</li>\n</ol>\n<p>Let's take the simple case where <code class=\"language-text\">a = &quot;aaa&quot;</code> and <code class=\"language-text\">b = &quot;aaaaa&quot;</code>. Imagine for a moment that we were using the earlier method of expanding the entire memoisation table - it would look like this. </p>\n<table>\n<thead>\n<tr>\n<th></th>\n<th align=\"right\">''</th>\n<th align=\"right\">a</th>\n<th align=\"right\">a</th>\n<th align=\"right\">a</th>\n<th align=\"right\">a</th>\n<th align=\"right\">a</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>''</td>\n<td align=\"right\">0</td>\n<td align=\"right\">1</td>\n<td align=\"right\">2</td>\n<td align=\"right\">3</td>\n<td align=\"right\">4</td>\n<td align=\"right\">5</td>\n</tr>\n<tr>\n<td>a</td>\n<td align=\"right\">1</td>\n<td align=\"right\">0</td>\n<td align=\"right\">1</td>\n<td align=\"right\">2</td>\n<td align=\"right\">3</td>\n<td align=\"right\">4</td>\n</tr>\n<tr>\n<td>a</td>\n<td align=\"right\">2</td>\n<td align=\"right\">1</td>\n<td align=\"right\">0</td>\n<td align=\"right\">1</td>\n<td align=\"right\">2</td>\n<td align=\"right\">3</td>\n</tr>\n<tr>\n<td>a</td>\n<td align=\"right\">3</td>\n<td align=\"right\">2</td>\n<td align=\"right\">1</td>\n<td align=\"right\">0</td>\n<td align=\"right\">1</td>\n<td align=\"right\">2</td>\n</tr>\n</tbody>\n</table>\n<p>Because we are lazily evaluating the entire table not all of these values will be filled in, but for now this gives us a visual representation of what we are trying to do. For this simplified example, in theory we should ever only need to calculate the values marked by <code class=\"language-text\">X</code> and <code class=\"language-text\">Y</code> here. The <code class=\"language-text\">Y</code> values need to be known as we look at the NW, W and N values of a particular entry to determine <code class=\"language-text\">X</code>. </p>\n<table>\n<thead>\n<tr>\n<th></th>\n<th align=\"right\">''</th>\n<th align=\"right\">a</th>\n<th align=\"right\">a</th>\n<th align=\"right\">a</th>\n<th align=\"right\">a</th>\n<th align=\"right\">a</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>''</td>\n<td align=\"right\">X</td>\n<td align=\"right\">Y</td>\n<td align=\"right\">2</td>\n<td align=\"right\">3</td>\n<td align=\"right\">4</td>\n<td align=\"right\">5</td>\n</tr>\n<tr>\n<td>a</td>\n<td align=\"right\">Y</td>\n<td align=\"right\">X</td>\n<td align=\"right\">Y</td>\n<td align=\"right\">2</td>\n<td align=\"right\">3</td>\n<td align=\"right\">4</td>\n</tr>\n<tr>\n<td>a</td>\n<td align=\"right\">2</td>\n<td align=\"right\">Y</td>\n<td align=\"right\">X</td>\n<td align=\"right\">Y</td>\n<td align=\"right\">2</td>\n<td align=\"right\">3</td>\n</tr>\n<tr>\n<td>a</td>\n<td align=\"right\">3</td>\n<td align=\"right\">2</td>\n<td align=\"right\">Y</td>\n<td align=\"right\">X</td>\n<td align=\"right\">1</td>\n<td align=\"right\">2</td>\n</tr>\n</tbody>\n</table>\n<p>It suggests that we need to rethink the way we represent the table. Instead of rows and columns, we structure our data as 3 diagonal groups instead. This allows us to better enforce our intended order of evaluation.</p>\n<div class=\"gatsby-highlight\" data-language=\"hs\"><pre class=\"language-hs\"><code class=\"language-hs\"><span class=\"token hvariable\">mainDiag</span> <span class=\"token operator\">::</span> <span class=\"token punctuation\">[</span><span class=\"token constant\">Int</span><span class=\"token punctuation\">]</span>\n<span class=\"token hvariable\">mainDiag</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token number\">0</span><span class=\"token punctuation\">]</span>\n\n<span class=\"token hvariable\">lowers</span> <span class=\"token operator\">::</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">[</span><span class=\"token constant\">Int</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span>\n<span class=\"token hvariable\">lower</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>\n    <span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">[</span><span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token number\">2</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">[</span><span class=\"token number\">3</span><span class=\"token punctuation\">]</span>\n<span class=\"token punctuation\">]</span>\n\n<span class=\"token hvariable\">uppers</span> <span class=\"token operator\">::</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">[</span><span class=\"token constant\">Int</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span>\n<span class=\"token hvariable\">uppers</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>\n    <span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">[</span><span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token number\">2</span><span class=\"token punctuation\">,</span> <span class=\"token number\">2</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">[</span><span class=\"token number\">3</span><span class=\"token punctuation\">,</span> <span class=\"token number\">3</span><span class=\"token punctuation\">,</span> <span class=\"token number\">3</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">[</span><span class=\"token number\">4</span><span class=\"token punctuation\">,</span> <span class=\"token number\">4</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">[</span><span class=\"token number\">5</span><span class=\"token punctuation\">]</span>\n<span class=\"token punctuation\">]</span></code></pre></div>\n<p>One thing we notice is that if <code class=\"language-text\">len(a) == len(b)</code>, the last value in <code class=\"language-text\">mainDiag</code> is our answer. Otherwise if <code class=\"language-text\">len(a) != len(b)</code>, we look in either <code class=\"language-text\">lowers</code> or <code class=\"language-text\">uppers</code> for the corresponding corner value.</p>\n<p>Depending on the input strings of course, this path starting in the top-left can snake to the left or the right of the table and cause further evaluation of <code class=\"language-text\">uppers</code> or <code class=\"language-text\">lowers</code>. This change in direction is governed by our simple <code class=\"language-text\">minimum [W, NW, N]</code> when a point mutation is required. Where possible we prefer expanding in one direction rather than in both. The wonderful solution to this problem was to simply introduce:</p>\n<div class=\"gatsby-highlight\" data-language=\"hs\"><pre class=\"language-hs\"><code class=\"language-hs\"><span class=\"token hvariable\">specialMin3</span> <span class=\"token hvariable\">a</span> <span class=\"token hvariable\">b</span> <span class=\"token hvariable\">c</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">if</span> <span class=\"token hvariable\">a</span> <span class=\"token operator\">&lt;</span> <span class=\"token hvariable\">b</span> <span class=\"token keyword\">then</span> <span class=\"token hvariable\">a</span> <span class=\"token keyword\">else</span> <span class=\"token builtin\">min</span> <span class=\"token hvariable\">b</span> <span class=\"token hvariable\">c</span></code></pre></div>\n<p>Now we worry about how to fill in our values. <code class=\"language-text\">lowers</code> is represented by L, <code class=\"language-text\">mainDiag</code> by M, and <code class=\"language-text\">uppers</code> by U. We initialise our 3 diagonal stores to depend on their NW, W and N values. To construct the next value of <code class=\"language-text\">mainDiag</code> here for example, it needs to take as input <code class=\"language-text\">head uppers</code> and <code class=\"language-text\">head lowers</code>. <em>This is allowed even if <code class=\"language-text\">uppers</code> and <code class=\"language-text\">lowers</code> have not been evaluated.</em> Coming from an imperative programming background, this was something quite difficult to wrap my head around, but reading more about thunks and how functional programming works was incredibly useful in bridging this gap.</p>\n<table>\n<thead>\n<tr>\n<th></th>\n<th align=\"right\">''</th>\n<th align=\"right\">a</th>\n<th align=\"right\">a</th>\n<th align=\"right\">a</th>\n<th align=\"right\">a</th>\n<th align=\"right\">a</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>''</td>\n<td align=\"right\">M</td>\n<td align=\"right\">U</td>\n<td align=\"right\">-</td>\n<td align=\"right\">-</td>\n<td align=\"right\">-</td>\n<td align=\"right\">-</td>\n</tr>\n<tr>\n<td>a</td>\n<td align=\"right\">L</td>\n<td align=\"right\">?</td>\n<td align=\"right\">-</td>\n<td align=\"right\">-</td>\n<td align=\"right\">-</td>\n<td align=\"right\">-</td>\n</tr>\n<tr>\n<td>a</td>\n<td align=\"right\">-</td>\n<td align=\"right\">-</td>\n<td align=\"right\">-</td>\n<td align=\"right\">-</td>\n<td align=\"right\">-</td>\n<td align=\"right\">-</td>\n</tr>\n<tr>\n<td>a</td>\n<td align=\"right\">-</td>\n<td align=\"right\">-</td>\n<td align=\"right\">-</td>\n<td align=\"right\">-</td>\n<td align=\"right\">-</td>\n<td align=\"right\">-</td>\n</tr>\n</tbody>\n</table>\n<p>And that's it! This sums up the main points I had trouble with understanding the algorithm. This is a copy of the implementation provided in the <a href=\"http://users.monash.edu/~lloyd/tildeStrings/Alignment/92.IPL.html\">paper</a>, translated to Haskell and commented.</p>\n<div class=\"gatsby-highlight\" data-language=\"hs\"><pre class=\"language-hs\"><code class=\"language-hs\"><span class=\"token comment\">-- | Solve the edit distance problem</span>\n<span class=\"token hvariable\">lazyDynProgEd</span> <span class=\"token operator\">::</span> \n    <span class=\"token constant\">String</span>      <span class=\"token comment\">-- | first string a</span>\n    <span class=\"token operator\">-></span> <span class=\"token constant\">String</span>   <span class=\"token comment\">-- | second string b</span>\n    <span class=\"token operator\">-></span> <span class=\"token constant\">Int</span>      <span class=\"token comment\">-- | output to our edit distance problem</span>\n<span class=\"token hvariable\">lazyDynProgEd</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> <span class=\"token hvariable\">b</span> <span class=\"token operator\">=</span> <span class=\"token builtin\">length</span> <span class=\"token hvariable\">b</span>\n<span class=\"token hvariable\">lazyDynProgEd</span> <span class=\"token hvariable\">a</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token builtin\">length</span> <span class=\"token hvariable\">a</span>\n<span class=\"token hvariable\">lazyDynProgEd</span> <span class=\"token hvariable\">a</span> <span class=\"token hvariable\">b</span> <span class=\"token operator\">=</span> \n    <span class=\"token keyword\">let</span> <span class=\"token hvariable\">mainDiag</span> <span class=\"token operator\">=</span> <span class=\"token hvariable\">oneDiag</span> <span class=\"token hvariable\">a</span> <span class=\"token hvariable\">b</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">head</span> <span class=\"token hvariable\">uppers</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token operator\">:</span><span class=\"token punctuation\">(</span><span class=\"token builtin\">head</span> <span class=\"token hvariable\">lowers</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>     <span class=\"token comment\">-- | -1 initialises the top-left square in the mainDiag to 0</span>\n        <span class=\"token hvariable\">uppers</span> <span class=\"token operator\">=</span> <span class=\"token hvariable\">eachDiag</span> <span class=\"token hvariable\">a</span> <span class=\"token hvariable\">b</span> <span class=\"token punctuation\">(</span><span class=\"token hvariable\">mainDiag</span><span class=\"token operator\">:</span><span class=\"token hvariable\">uppers</span><span class=\"token punctuation\">)</span>                     <span class=\"token comment\">-- | uppers passed to eachDiag expands to form the remaining diags</span>\n        <span class=\"token hvariable\">lowers</span> <span class=\"token operator\">=</span> <span class=\"token hvariable\">eachDiag</span> <span class=\"token hvariable\">b</span> <span class=\"token hvariable\">a</span> <span class=\"token punctuation\">(</span><span class=\"token hvariable\">mainDiag</span><span class=\"token operator\">:</span><span class=\"token hvariable\">lowers</span><span class=\"token punctuation\">)</span>                     <span class=\"token comment\">-- | lowers passed to eachDiag expands to form the remaining diags</span>\n        <span class=\"token comment\">-- | Constructor for a diagonal between diagAbove and diagBelow which lazily expands as values become known</span>\n        <span class=\"token hvariable\">oneDiag</span> <span class=\"token operator\">::</span> \n            <span class=\"token constant\">String</span>      <span class=\"token comment\">-- | first string a</span>\n            <span class=\"token operator\">-></span> <span class=\"token constant\">String</span>   <span class=\"token comment\">-- | second string b</span>\n            <span class=\"token operator\">-></span> <span class=\"token punctuation\">[</span><span class=\"token constant\">Int</span><span class=\"token punctuation\">]</span>    <span class=\"token comment\">-- | diagAbove</span>\n            <span class=\"token operator\">-></span> <span class=\"token punctuation\">[</span><span class=\"token constant\">Int</span><span class=\"token punctuation\">]</span>    <span class=\"token comment\">-- | diagBelow</span>\n            <span class=\"token operator\">-></span> <span class=\"token punctuation\">[</span><span class=\"token constant\">Int</span><span class=\"token punctuation\">]</span>    <span class=\"token comment\">-- | edit distance values for the middle diagonal</span>\n        <span class=\"token hvariable\">oneDiag</span> <span class=\"token hvariable\">a</span> <span class=\"token hvariable\">b</span> <span class=\"token hvariable\">diagAbove</span> <span class=\"token hvariable\">diagBelow</span> <span class=\"token operator\">=</span>\n            <span class=\"token keyword\">let</span> \n                <span class=\"token hvariable\">doDiag</span> <span class=\"token operator\">::</span> \n                    <span class=\"token constant\">String</span>      <span class=\"token comment\">-- | the remaining characters of string a to be compared</span>\n                    <span class=\"token operator\">-></span> <span class=\"token constant\">String</span>   <span class=\"token comment\">-- | the remaining characters of string b to be compared</span>\n                    <span class=\"token operator\">-></span> <span class=\"token constant\">Int</span>      <span class=\"token comment\">-- | nw element to the current square in the diagonal (the previous element in this diagonal)</span>\n                    <span class=\"token operator\">-></span> <span class=\"token punctuation\">[</span><span class=\"token constant\">Int</span><span class=\"token punctuation\">]</span>    <span class=\"token comment\">-- | diagAbove</span>\n                    <span class=\"token operator\">-></span> <span class=\"token punctuation\">[</span><span class=\"token constant\">Int</span><span class=\"token punctuation\">]</span>    <span class=\"token comment\">-- | diagBelow</span>\n                    <span class=\"token operator\">-></span> <span class=\"token punctuation\">[</span><span class=\"token constant\">Int</span><span class=\"token punctuation\">]</span>    <span class=\"token comment\">-- | edit distance values for the middle diagonal from the 2 input strings</span>\n                <span class=\"token hvariable\">doDiag</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> <span class=\"token hvariable\">_</span> <span class=\"token hvariable\">_</span> <span class=\"token hvariable\">_</span> <span class=\"token hvariable\">_</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span>\n                <span class=\"token hvariable\">doDiag</span> <span class=\"token hvariable\">_</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> <span class=\"token hvariable\">_</span> <span class=\"token hvariable\">_</span> <span class=\"token hvariable\">_</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span>\n                <span class=\"token hvariable\">doDiag</span> <span class=\"token punctuation\">(</span><span class=\"token hvariable\">ax</span><span class=\"token operator\">:</span><span class=\"token hvariable\">axs</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">(</span><span class=\"token hvariable\">bx</span><span class=\"token operator\">:</span><span class=\"token hvariable\">bxs</span><span class=\"token punctuation\">)</span> <span class=\"token hvariable\">nw</span> <span class=\"token hvariable\">n</span> <span class=\"token hvariable\">w</span> <span class=\"token operator\">=</span>\n                    <span class=\"token keyword\">let</span> <span class=\"token hvariable\">me</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">if</span> <span class=\"token hvariable\">ax</span> <span class=\"token operator\">==</span> <span class=\"token hvariable\">bx</span> <span class=\"token keyword\">then</span> <span class=\"token hvariable\">nw</span>\n                        <span class=\"token keyword\">else</span> <span class=\"token number\">1</span> <span class=\"token operator\">+</span> <span class=\"token hvariable\">specialMin3</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">head</span> <span class=\"token hvariable\">w</span><span class=\"token punctuation\">)</span> <span class=\"token hvariable\">nw</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">head</span> <span class=\"token hvariable\">n</span><span class=\"token punctuation\">)</span>\n                    <span class=\"token keyword\">in</span> <span class=\"token hvariable\">me</span><span class=\"token operator\">:</span><span class=\"token punctuation\">(</span><span class=\"token hvariable\">doDiag</span> <span class=\"token hvariable\">axs</span> <span class=\"token hvariable\">bxs</span> <span class=\"token hvariable\">me</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">tail</span> <span class=\"token hvariable\">n</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">tail</span> <span class=\"token hvariable\">w</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n                <span class=\"token hvariable\">firstElement</span> <span class=\"token operator\">=</span> <span class=\"token number\">1</span> <span class=\"token operator\">+</span> <span class=\"token builtin\">head</span> <span class=\"token hvariable\">diagBelow</span>\n                <span class=\"token hvariable\">thisDiag</span> <span class=\"token operator\">=</span> <span class=\"token hvariable\">firstElement</span><span class=\"token operator\">:</span><span class=\"token punctuation\">(</span><span class=\"token hvariable\">doDiag</span> <span class=\"token hvariable\">a</span> <span class=\"token hvariable\">b</span> <span class=\"token hvariable\">firstElement</span> <span class=\"token hvariable\">diagAbove</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">tail</span> <span class=\"token hvariable\">diagBelow</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n            <span class=\"token keyword\">in</span> <span class=\"token hvariable\">thisDiag</span>\n        <span class=\"token comment\">-- | Constructor for either upper or lower diagonals. The functions a', bx', and bx' are apostrophed to differentiate them from strings a and b in the outer scope.</span>\n        <span class=\"token hvariable\">eachDiag</span> <span class=\"token operator\">::</span> \n            <span class=\"token constant\">String</span>      <span class=\"token comment\">-- | first string a'</span>\n            <span class=\"token operator\">-></span> <span class=\"token constant\">String</span>   <span class=\"token comment\">-- | the remaining characters of string b' to be compared</span>\n            <span class=\"token operator\">-></span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">[</span><span class=\"token constant\">Int</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span>  <span class=\"token comment\">-- | (lastDiag which started from bx'):(list of diagonals from comparing the remaining characters in bxs')</span>\n            <span class=\"token operator\">-></span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">[</span><span class=\"token constant\">Int</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span>  <span class=\"token comment\">-- | a list containing all diagonals from comparing the remaining characters in b'</span>\n        <span class=\"token hvariable\">eachDiag</span> <span class=\"token hvariable\">a</span>' <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span> <span class=\"token hvariable\">diags</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span>\n        <span class=\"token hvariable\">eachDiag</span> <span class=\"token hvariable\">a</span>' <span class=\"token punctuation\">(</span><span class=\"token hvariable\">bx</span>'<span class=\"token operator\">:</span><span class=\"token hvariable\">bxs</span>'<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">(</span><span class=\"token hvariable\">lastDiag</span><span class=\"token operator\">:</span><span class=\"token hvariable\">diags</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=</span>\n            <span class=\"token keyword\">let</span> <span class=\"token hvariable\">nextDiag</span> <span class=\"token operator\">=</span> <span class=\"token builtin\">head</span> <span class=\"token operator\">$</span> <span class=\"token builtin\">tail</span> <span class=\"token hvariable\">diags</span>                    <span class=\"token comment\">-- | grab the successor of thisDiag in uppers/lowers to form thisDiag</span>\n                <span class=\"token hvariable\">thisDiag</span> <span class=\"token operator\">=</span> <span class=\"token hvariable\">oneDiag</span> <span class=\"token hvariable\">a</span>' <span class=\"token hvariable\">bxs</span>' <span class=\"token hvariable\">nextDiag</span> <span class=\"token hvariable\">lastDiag</span>\n            <span class=\"token keyword\">in</span> <span class=\"token hvariable\">thisDiag</span><span class=\"token operator\">:</span><span class=\"token punctuation\">(</span><span class=\"token hvariable\">eachDiag</span> <span class=\"token hvariable\">a</span>' <span class=\"token hvariable\">bxs</span>' <span class=\"token hvariable\">diags</span><span class=\"token punctuation\">)</span>\n        <span class=\"token hvariable\">lengthDiff</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">length</span> <span class=\"token hvariable\">a</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">length</span> <span class=\"token hvariable\">b</span><span class=\"token punctuation\">)</span>\n    <span class=\"token comment\">-- | only evaluate what is necessary</span>\n    <span class=\"token keyword\">in</span> <span class=\"token builtin\">last</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">if</span> <span class=\"token hvariable\">lengthDiff</span> <span class=\"token operator\">==</span> <span class=\"token number\">0</span> <span class=\"token keyword\">then</span> <span class=\"token hvariable\">mainDiag</span> \n    <span class=\"token keyword\">else</span> <span class=\"token keyword\">if</span> <span class=\"token hvariable\">lengthDiff</span> <span class=\"token operator\">></span> <span class=\"token number\">0</span> <span class=\"token keyword\">then</span> <span class=\"token punctuation\">(</span><span class=\"token hvariable\">lowers</span> <span class=\"token operator\">!!</span> <span class=\"token punctuation\">(</span><span class=\"token hvariable\">lengthDiff</span><span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> \n    <span class=\"token keyword\">else</span> <span class=\"token punctuation\">(</span><span class=\"token hvariable\">uppers</span> <span class=\"token operator\">!!</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">abs</span> <span class=\"token punctuation\">(</span><span class=\"token hvariable\">lengthDiff</span><span class=\"token punctuation\">)</span><span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></code></pre></div>\n<div class=\"gatsby-highlight\" data-language=\"hs\"><pre class=\"language-hs\"><code class=\"language-hs\"><span class=\"token comment\">-- | always expand lowers if possible</span>\n<span class=\"token hvariable\">specialMin3</span> <span class=\"token operator\">::</span> <span class=\"token constant\">Ord</span> <span class=\"token hvariable\">a</span> <span class=\"token operator\">=></span> <span class=\"token hvariable\">a</span> <span class=\"token operator\">-></span> <span class=\"token hvariable\">a</span> <span class=\"token operator\">-></span> <span class=\"token hvariable\">a</span> <span class=\"token operator\">-></span> <span class=\"token hvariable\">a</span>\n<span class=\"token hvariable\">specialMin3</span> <span class=\"token hvariable\">a</span> <span class=\"token hvariable\">b</span> <span class=\"token hvariable\">c</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">if</span> <span class=\"token hvariable\">a</span> <span class=\"token operator\">&lt;</span> <span class=\"token hvariable\">b</span> <span class=\"token keyword\">then</span> <span class=\"token hvariable\">a</span> <span class=\"token keyword\">else</span> <span class=\"token builtin\">min</span> <span class=\"token hvariable\">b</span> <span class=\"token hvariable\">c</span></code></pre></div>\n<h2>Final thoughts</h2>\n<p>The paper explains the algorithm more concisely and it is worth reading. My thoughts here are about the points that I didn't quite appreciate until I had a closer look at this, at face value, complex algorithm, so I hope it was at least somewhat useful for the reader. Do visit the repo <a href=\"https://github.com/asherLZR/lazy-dynamic-programming\">here</a> and if you like, make changes and run the tests provided.</p>\n<h2>References</h2>\n<p>Allison, L. (1992). Lazy dynamic-programming can be eager. Information Processing Letters, 43(4), 207-212. doi:10.1016/0020-0190(92)90202-7</p>","timeToRead":11,"frontmatter":{"date":"11 April 2020","title":"Lazy Dynamic-Programming for Edit Distance","summary":"Using the power of lazy evaluation to solve an old favourite, yet current problem."}}},"pageContext":{"slug":"/blog/lazy-dynamic-programming"}},"staticQueryHashes":["671693147","671693147"]}