2012-04-04 256 views
0

我想在Haskell中编写一个简单的迭代算法,但我正努力寻找优雅和速度方面的最佳解决方案。在Haskell中用最终迭代的条件和不同的迭代步骤最佳迭代

我有一个算法,需要应用一个操作到一个状态多次迭代,直到达到一些停止条件,记录状态使用一些任意函数。我已经知道如何通过定义像iterateM这样的函数来实现这样的方案。

但是在这种情况下,对每个步骤执行的操作取决于状态,并归结为检查'步骤类型'条件以决定下一个迭代类型,然后对接下来的10次迭代执行操作A,或者在再次检查条件之前对下一次迭代执行操作B.

我可以在一个命令行式风格写为:

c=0 
while True: 
    if c>0: 
     x=iterateByA(x) 
     c=c-1 
    else: 
     if stepCondition(x)==0: 
      x=iterateByA(x) 
      c=9 
     else: 
      x=iterateByB(x) 
    observeState(x) 
    if stopCondition(x): 
     break 

,当然这可能只是在Haskell被复制的,但我宁愿做一些更优雅。

我的想法是让迭代使用函数列表来弹出并应用到状态,并且一旦它为空就用新的列表(基于“步骤类型”条件)更新该列表。我略微担心,这将是无效的。会这样做,并使用类似

take 10 (repeat iterateByA) 

编译掉所有的列表分配等,只有使用计数器,如上面的命令一个紧密循环?

是否还有另一种干净而有效的方法呢?

如果这对自适应随机模拟算法有帮助,则迭代步骤会更新状态,而步骤条件(决定最佳模拟方案)是当前状态的函数。实际上有3种不同的迭代方案,但我认为使用2的例子更容易解释。

(我不知道,如果它的问题,但我应该还指出,在Haskell的iterateByX功能是一元,因为他们使用的随机数。)

回答

1

直接翻译看起来并不太坏。

loop c x 
    | stopCondition x = observe x 
    | c > 0   = observe x >> iterateByA x >>= loop (c-1) 
    | stepCondition x = observe x >> iterateByA x >>= loop 9 
    | otherwise  = observe x >> iterateByB x >>= loop c 

重复observe可以通过各种技巧删除,如果你不喜欢它。

不过你应该重新考虑一下。这是非常必要的方法;大概可以做得更好(但是很难从你在这里给出的几个细节中说出)。

+0

这是一样的吗? OP代码在'x'的突变版本上调用'observeState',而您的版本在预先突变版本上调用'observe'。此外'stopCondition'的情况在循环结束时进行测试,而不是开始。 – pat 2012-04-04 20:14:09

+0

@pat我不会惊讶地发现我的代码中有一个错误的错误。不过,我几乎认为这不是问题所在。 – 2012-04-04 20:21:54

+0

这实际上看起来不算太糟糕,但正如你所说,这是一个非常必要的方法。理想情况下,停止条件和观察函数应该是完全通用的,所以我们不需要解释多少,但是无论如何我都加了一点。 – Tom 2012-04-04 20:26:27