2012-04-04 29 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