[英]How to speed up (or memoize) a series of mutually recursive functions
我有一个程序,它产生一系列函数f
和g
,如下所示:
step (f,g) = (newF f g, newG f g)
newF f g x = r (f x) (g x)
newG f g x = s (f x) (g x)
foo = iterate step (f0,g0)
其中r和s是fx
和gx
一些无趣功能。 我天真地希望将foo
作为列表意味着当我调用第n个f
时它将不会重新计算(n-1) f
如果它已经计算过它(如果f
和g
不是这样的话会发生的话)功能)。 是否有任何方法可以记住这一点而不会将整个程序拆开(例如,在所有相关参数上评估f0
和g0
然后向上工作)?
您可能会发现Data.MemoCombinators很有用(在data-memocombinators包中)。
你没有说你的f
和g
采用什么参数类型 - 如果它们都采用整数值,那么你会像这样使用它:
import qualified Data.MemoCombinators as Memo
foo = iterate step (Memo.integral f0, Memo.integral g0)
如果需要,您也可以记住每个步骤的输出
step (f,g) = (Memo.integral (newF f g), Memo.integral (newG f g))
我希望你不要把整个程序分开。
在回复你的评论时:
这是我能想到的最好的。 它未经测试,但应该沿着正确的方向工作。
我担心Double
和Rational
之间的转换是不必要的低效 - 如果有一个Double
的Bits
实例,我们可以使用Memo.bits
。 所以这对你来说可能最终没有任何实际用途。
import Control.Arrow ((&&&))
import Data.Ratio (numerator, denominator, (%))
memoV :: Memo.Memo a -> Memo.Memo (V a)
memoV m f = \(V x y z) -> table x y z
where g x y z = f (V x y z)
table = Memo.memo3 m m m g
memoRealFrac :: RealFrac a => Memo.Memo a
memoRealFrac f = Memo.wrap (fromRational . uncurry (%))
((numerator &&& denominator) . toRational)
Memo.integral
一种不同的方法。
你有
step :: (V Double -> V Double, V Double -> V Double)
-> (V Double -> V Double, V Double -> V Double)
你怎么改变它
step :: (V Double -> (V Double, V Double))
-> (V Double -> (V Double, V Double))
step h x = (r fx gx, s fx gx)
where (fx, gx) = h x
而且也改变了
foo = (fst . bar, snd . bar)
where bar = iterate step (f0 &&& g0)
希望共享的fx
和gx
应该会导致一些加速。
是否有任何方法可以记住这一点而不会将整个程序拆开(例如,在所有相关参数上评估f0和g0然后向上工作)?
这可能就是“将整个程序拆开”的意思,但这里有一个解决方案(我相信但不能测试ATM) fooX
可以共享。
nthFooOnX :: Integer -> Int -> (Integer, Integer)
nthFooOnX x =
let fooX = iterate step' (f0 x, g0 x)
in \n-> fooX !! n
step' (fx,gx) = (r fx gx, s fx gx)
-- testing definitions:
r = (+)
s = (*)
f0 = (+1)
g0 = (+1)
我不知道这是否保留了原始实施的精神。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.