Trying to implement a simple dynamic programming algorithm for a Knapsack problem. Obviously, this approach uses a lot of memory, so I'm trying to optimize the memory used. I'm just trying to save only the previous row of the table in memory long enough to calculate the next row and so on. At first I thought that my implementation was solid, but it still ran out of memory as an implementation designed to store the entire table. So I thought that I might need it foldl'instead foldr, but it does not make any difference. My program continues to consume memory until my system runs out.
So, I have 2 specific questions:
- What is my code that uses all the memory? I thought I was smart using the fold because I assumed that only the current battery value would be stored in memory.
- What is the right approach to achieve my goal; that is, keeping only the very last line in memory? I don’t need the code, perhaps only some useful functions and data types. More generally, what are some tips and techniques for understanding memory usage in Haskell?
Here is my implementation
data KSItem a = KSItem { ksItem :: a, ksValue :: Int, ksWeight :: Int} deriving (Eq, Show, Ord)
dynapack5 size items = finalR ! size
where
noItems = length items
itemsArr = listArray(1,noItems) items
row = listArray(1,size) (replicate size (0,[]))
computeRow row item =
let w = ksWeight item
v = ksValue item
idx = ksItem item
pivot = let (lastVal, selections) = row ! w
in if v > lastVal
then (v, [idx])
else (lastVal, selections)
figure r c =
if (prevVal + v) > lastVal
then (prevVal + v, prevItems ++ [idx])
else (lastVal, lastItems)
where (lastVal, lastItems) = (r ! c)
(prevVal, prevItems) = (r ! (c - w))
theRest = [ (figure row cw) | cw <- [(w+1)..size] ]
newRow = (map (row!) [1..(w-1)]) ++
[pivot] ++
theRest
in listArray (1,size) newRow
finalR = foldl' computeRow row items
In my head, what I think it does is initialize the first line (0, []) ... it repeats as necessary, and then discards the fold, where the next line is calculated based on the supplied line, and this value becomes the battery . I do not see where more and more memory is being consumed ...
: , \\ ?