gpt4 book ai didi

haskell - 有什么阻碍优化尾递归吗?

转载 作者:行者123 更新时间:2023-12-02 09:31:18 26 4
gpt4 key购买 nike

我正在使用动态规划在 Haskell 中解决背包问题。我的第一次尝试是构建一个二维表。但是当输入很大时(例如100 * 3190802表),内存很容易被炸毁。

知道任何给定的行 i 仅取决于行 (i - 1),因此我编写了一个函数,希望能够利用尾递归:

import Data.Vector (Vector, (!))
import qualified Data.Vector as V

-- n items, k capacity, vs values, ws weights
ans:: Int -> Int -> Vector Int -> Vector Int -> Int
ans n k vs ws =
let row = initRow k vs ws
in row ! k

initRow :: Int -> Vector Int -> Vector Int -> Vector Int
initRow k vs ws = itbl 1 $ V.replicate (k + 1) 0
where n = V.length vs
itbl i row
| i > n = row
| otherwise = itbl (i + 1) $ V.generate (k + 1) gen
where gen w =
let w_i = ws ! (i - 1)
no_i = row ! w
ok_i = row ! (w - w_i) + (vs ! (i - 1))
in
if w < w_i then no_i
else max no_i ok_i

如代码所示,itbl 递归地调用自身,并且不会对其返回值进行进一步的计算。然而,我仍然看到 top 中的内存在不断增长:

 VIRT   PID USER      PR  NI  RES  SHR S  %CPU %MEM    TIME+  COMMAND
1214m 9878 root 20 0 424m 1028 S 40.8 85.6 0:16.80 ghc

代码中是否有任何内容阻止编译器为尾递归生成优化代码?

code data

--

最佳答案

这是一个严格性问题。调用 generate 中的

             | otherwise = itbl (i + 1) $ V.generate (k + 1) gen

实际上并没有强制向量进入内存。

您可以导入 Control.DeepSeq 并用深度严格的应用程序 $!! 替换 $:

             | otherwise = itbl (i + 1) $!! V.generate (k + 1) gen

或者您可以使用未装箱的向量(这可能更快),方法是将导入语句更改为

import Data.Vector.Unboxed (Vector, (!))
import qualified Data.Vector.Unboxed as V

(并将其他所有内容保留在原始程序中)。

关于haskell - 有什么阻碍优化尾递归吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17346161/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com