【发布时间】:2022-01-29 03:39:35
【问题描述】:
我在 Haskell 中编写了一个函数来计算矩阵的行列式,它工作得很好,但速度非常慢,所以我试着像 Haskell Wiki does with the Fibonacci function 一样记住它。
但不知何故,我的记忆函数比非记忆函数花费的时间略长,即使在计算单位矩阵的行列式时也是如此,这应该从记忆中受益匪浅。
我也尝试使用 Map 来缓存结果,但没有办法将修改后的 Map 传递给递归函数的下一次迭代。
我该如何解决这个问题?
-- Non-Memoized version
det :: (Num a, Eq a) => [[a]] -> a
det x
| fst s == 0 = 0
| fst s == 1 = head $ head x
| fst s == 2 = (head (head x) * ((x !! 1) !! 1))
- ((head x !! 1) * head (x !! 1))
| F.allEqual x = 0
| otherwise = sum [((-1) ^ (i + 1)) * head (x !! (i - 1))
* det (sub x i 1)
| i <- [1..(fst s)]]
where
s = shape x
-- Memoized version
mDet :: (Num a, Eq a) => [[a]] -> a
mDet x = sum [((-1) ^ (i + 1)) * head (x !! (i - 1))
* det' (sub x i 1)
| i <- [1..(fst $ shape x)]]
where
det' y
| fst s == 0 = 0
| fst s == 1 = head $ head y
| fst s == 2 = (head (head y) * ((y !! 1) !! 1))
- ((head y !! 1) * head (y !! 1))
| F.allEqual y = 0
| otherwise = mDet y
where
s = shape y
【问题讨论】:
-
你忘了定义 shape 和 F.allEqual。
-
我认为这很明显,shape 是一个具有矩阵维度的元组,allEqual 检查列表的所有元素是否相等,正如我在问题中所说,该函数有效,唯一的问题是它的记忆
-
这不是记忆。没有存储中间结果以供重用的数据结构。这看起来完全一样的功能,只是递归分为两步。
-
是的,确实没有正确记忆,但这就是我首先问的原因
标签: haskell recursion linear-algebra memoization determinants