使用延迟评估来计算数字网格

时间:2015-07-29 22:50:53

标签: haskell lazy-evaluation

f m x成为计算上昂贵的函数,它接受两个参数并使用数值算法计算。 fdifferentiable函数,具有f m x的派生等于f m+1 x的属性。

为了降低调用此函数的计算成本数千次,我们可以在xk周围的6项泰勒级数中扩展它,

f(m,x) = f(m,xk + dx) = f(m,xk) -f(m+1,xk)*dx + 0.5*f(m+2,xk)(dx)^2 - 1/6 * f(m+3,xk)(dx)^3 + 1/24 * f(m+4,xk)(dx)^4  + 1/120 * f(m+5,xk)(dx)^5......

f(m+1,xk)f m的第一个派生。

使用泰勒系列,我们可以在xk维度中生成[0.1, 0.2, ..xk,.. xmax]mmax + 6的网格,其中xmaxmmax是{的最大值分别为{1}}和x。基本上,我们的想法是填充网格的节点,调用昂贵的函数m,并使用上面的泰勒级数展开计算节点之间函数的值。

可以使用惰性地图

生成此网格
f

我们有一个网格,其中每个节点都是昂贵函数import Control.Applicative ((<$>),(<*>)) import Data.Map.Lazy as M data Fun = Fun Double Double deriving (Ord,Eq) -- data representing the point f m x generateGrid :: (Double -> Double -> Double)-> Int -> Int -> Double -> Map Fun Double generateGrid f mMax xmax delta = M.fromList $ zip keys vals where keys = Fun <$> [fromIntegral x | x <- [0..mMax]] <*> [delta*fromIntegral(i) | i <- [0..xmax]] vals = fmap (\(Fun m x) -> f m x) keys funTaylor :: Map Fun Double -> Double -> Double -> Double funTaylor grid m x = (fun m xk) - (fun (m+1) xk)*dx + 0.5*(fun (m+2) xk)*dx^2 - (1/6)*(fun (m+3) xk)*dx^3 + (1/24)*(fun (m+4) xk)*dx^4 - (1/120)*(fun (m+5) xk)*dx^5 where delta = 0.1 dx = x-xk xk = (calcClosestPoint x )* delta fun = calcutateFun grid calcClosestPoint r = fromIntegral $ floor $ x /delta calculateFun :: Map Fun Double -> Double -> Double -> Double calculateFun = .... 的一部分。现在,每当我们需要计算f时,我们都会调用f而不是funTaylor

请注意,这是一个虚拟网格,因为我们每次调用f时,只会评估泰勒系列中涉及的点,而网格的其余部分仍未评估。

现在假设我不知道先验数字funTaylor m xxmax是多少,这个虚拟空间很大,因此猜测极限并产生数百万thunk不是一个好选择。 然后,我们的想法是能够构建网格&#34; 动态&#34;,每次调用funTaylor函数时,新的条目都会添加到Map中。问题是mmax函数是从我的代码中的几个部分调用的,来自几个并行计算的函数。然后,我需要在调用funTaylor的所有函数之间共享网格。

另一种方法是创建一个频道或队列,它可以像网格和调用funTaylor的函数之间的服务器一样工作,每当需要新值funTaylor时,它就会被发送更新网格的队列,避免了在多个函数之间共享状态网格的问题。

问题是: 在运行中生成网格&#34; 的最佳方法是什么?&#34;

0 个答案:

没有答案