Note that there are some explanatory texts on larger screens.

plurals
  1. POEfficient table for Dynamic Programming in Haskell
    primarykey
    data
    text
    <p>I've coded up the <a href="http://en.wikipedia.org/wiki/Knapsack_problem#0-1_knapsack_problem" rel="nofollow noreferrer">0-1 Knapsack problem</a> in Haskell. I'm fairly proud about the laziness and level of generality achieved so far.</p> <p>I start by providing functions for creating and dealing with a lazy 2d matrix.</p> <pre><code>mkList f = map f [0..] mkTable f = mkList (\i -&gt; mkList (\j -&gt; f i j)) tableIndex table i j = table !! i !! j </code></pre> <p>I then make a specific table for a given knapsack problem</p> <pre><code>knapsackTable = mkTable f where f 0 _ = 0 f _ 0 = 0 f i j | ws!!i &gt; j = leaveI | otherwise = max takeI leaveI where takeI = tableIndex knapsackTable (i-1) (j-(ws!!i)) + vs!!i leaveI = tableIndex knapsackTable (i-1) j -- weight value pairs; item i has weight ws!!i and value vs!!i ws = [0,1,2, 5, 6, 7] -- weights vs = [0,1,7,11,21,31] -- values </code></pre> <p>And finish off with a couple helper functions for looking at the table</p> <pre><code>viewTable table maxI maxJ = take (maxI+1) . map (take (maxJ+1)) $ table printTable table maxI maxJ = mapM_ print $ viewTable table maxI maxJ </code></pre> <p>This much was pretty easy. But I want to take it a step further.</p> <p><strong>I want a better data structure for the table.</strong> Ideally, it should be</p> <ul> <li><s>Unboxed (immutable)</s> [edit] never mind this</li> <li>Lazy</li> <li>Unbounded</li> <li><code>O(1)</code> time to construct</li> <li><code>O(1)</code> time complexity for looking up a given entry,<br /> (more realistically, at worst <code>O(log n)</code>, where n is <code>i*j</code> for looking up the entry at row i, column j)</li> </ul> <p>Bonus points if you can explain why/how your solution satisfies these ideals.</p> <p>Also bonus points if you can further generalize <code>knapsackTable</code>, and prove that it is efficient.</p> <p>In improving the data structure you should try to satisfy the following goals:</p> <ul> <li>If I ask for the solution where the maximum weight is 10 (in my current code, that would be <code>indexTable knapsackTable 5 10</code>, the 5 means include items 1-5) only the minimal amount of work necessary should be performed. Ideally this means no <code>O(i*j)</code> work for forcing the spine of each row of the table to necessary column length. You could say this isn't "true" DP, if you believe DP means evaluating the entirety of the table.</li> <li>If I ask for the entire table to be printed (something like <code>printTable knapsackTable 5 10</code>), the values of each entry should be computed once and only once. The values of a given cell should depend on the values of other cells (DP style: the idea being, never recompute the same subproblem twice)</li> </ul> <hr> <p>Ideas:</p> <ul> <li><a href="http://hackage.haskell.org/packages/archive/array/latest/doc/html/Data-Array.html#t:Array" rel="nofollow noreferrer">Data.Array</a> bounded :(</li> <li><a href="http://hackage.haskell.org/packages/archive/array/latest/doc/html/Data-Array-Unboxed.html#t:UArray" rel="nofollow noreferrer">UArray</a> strict :(</li> <li><a href="https://stackoverflow.com/questions/4976908/how-are-dynamic-programming-algorithms-implemented-in-idiomatic-haskell">Memoization techniques</a> (SO question about DP in Haskell) this might work</li> </ul> <p>Answers that make some compromises to my stated ideals <em>will</em> be upvoted (by me, anyways) as long as they are informative. The answer with the least compromises will probably be the "accepted" one.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload