我遇到以下Haskell函数的问题:
evalPol :: Float
-> Float
-> Integer
-> Integer
-> (s -> a -> [(s, [(Float, Float)])])
-> (s -> a)
-> [s]
-> [((s -> Float), Float)]
-> [((s -> Float), Float)]
evalPol eps gamma maxIter nIter gen pol ss vofss =
if nIter >= maxIter || delta < eps
then reverse ((vofs', delta) : vofss)
else evalPol eps gamma maxIter (nIter + 1) gen pol ss ((vofs', delta) : vofss)
where delta = maximum [abs (vofs s - vofs' s) | s <- ss]
vofs' s = actVal gamma gen vofs s (pol s)
vofs = (fst . P.head) vofss
如果我用maxIter = 1
调用此函数并运行分析,那么我会看到函数入口计数,这对我来说很有意义:
evalPol..............2
evalPol.delta......1
evalPol.vofs'..441
上面的函数入口计数对我有意义,如下所示:
evalPol
输入两次:
maxIter = 1
,因此只允许一次递归调用。) evalPol.delta
只被调用一次,因为当第二次(递归地)调用evalPol
时,测试:nIter >= maxIter
成功,并且不需要评估{{} 1}}。
有意义的是我在delta
中获得了441个条目,因为我将该函数映射到列表evalPol.vofs'
上,并且该列表中有441个项目。
现在,如果我只进行一次更改:使用ss
调用evalPol
,我发现我的程序不会在合理的时间内终止。
允许它在中断之前运行几个小时,我得到以下内容:
maxIter = 2
evalPol................2
evalPol.delta........2
evalPol.vofs'..60366
的条目数从1变为2(参见上面的#2。)对我来说很有意义,因为我设置了evalPol.delta
。
但是,我不期望maxIter = 2
的条目数量大幅增加。
(我期待看到882个条目,每个允许递归441个。)
在evalPol.vofs'
中,evalPol.vofs'
中的条目数似乎是指数。
(我不知道这个,因为我没有让程序结束。)
如果我“展开”这2个递归的情况,寻找maxIter
的指数依赖,我得到:
maxIter
我看到正如预期的那样开发递归,但我没有看到任何嵌套调用-- This is how I call it from outside:
evalPol eps gamma 2 0 gen pol ss [((const 0), 0)] = -- Assume delta >= eps and recurse.
evalPol eps gamma 2 1 gen pol ss [(vofs', delta), ((const 0), 0)]
-- Now, expand delta
delta = maximum $ map (abs . uncurry (-) . (vofs &&& vofs')) ss -- Substitute for vofs, vofs', and pol, using previous iteration's definitions.
= maximum $ map ( abs
. uncurry (-)
. ( vofs' &&&
\s -> actVal gamma gen vofs' s 0
)
) ss
= maximum $ map ( abs
. uncurry (-)
. ( \s -> actVal gamma gen (const 0) s 0 &&&
\s -> actVal gamma gen (\s' -> actVal gamma gen (const 0) s' 0) s 0
)
) ss
,这可能解释了我所观察到的evalPol.vofs'
的(假设的)指数依赖。
此外,我查看了maxIter
函数以及actVal
函数,并且没有调用gen
隐藏在其中任何一个函数中。
所以,我无法向evalPol.vofs'
案例中的evalPol.vofs'
解释这些大量的条目。
答案 0 :(得分:1)
我通过使用vofs'
函数的向量表示来解决这个问题。
这样做已经消除了之前执行的冗余计算。我现在看到882次调用新的等效vofs'
,对于 2递归情况,这是我所期望的。也就是说,我希望evalPol
中maxIter
的执行时间为线性,并使用vofs'
的向量表示,这就是我所看到的。