7

私は Haskell でゲーム AI を書いています。指定された時間、ゲーム状態ツリーを検索したいです (つまり、AI がどの動きをするかを決定するのに 3 秒かかるようにしたいのです)。

Haskellのような純粋な言語でこれを行うにはどうすればよいですか? スレッドなどに飛び込む必要があると思いますが、できる限り最小限に抑えたいと思います。

4

3 に答える 3

5

1 つのアイデア: (@MathematicalOrchid によって提案された) をSafeSemaphoretimeoutの変更可能な変数と組み合わせて、プロセスが部分的な結果を計算するたびに中間値を格納します。

import Control.Monad
import Control.Concurrent.MSampleVar
import System.Timeout

fac :: Integer -> Integer
fac 0 = 1
fac n = n * fac (n - 1)

tmo :: Int -> ((a -> IO ()) -> IO ()) -> IO (Maybe a)
tmo ms f = do
    mvar <- newSV Nothing
    timeout ms (f (writeSV mvar . (Just $!)))
    readSV mvar

longComp :: (Integer -> IO ()) -> IO ()
longComp save = let loop n = save (fac n) >> loop (n + 1)
                in loop 0

main :: IO ()
main = tmo 10000 longComp >>= print

に渡された関数はtmo、最初の引数として、IO中間結果を保存するために使用できるアクションを取得します。タイムアウトになった場合は、最後に保存された結果が返されます。結果は WHNF に変換されるため、実際の計算は、結果が返されたときに結果を処理するスレッドではなく、結果を保存するスレッドで行われtmoます。

このバリアントでは、渡された関数はtmoその出力を保存する必要があり、それを返すことはできません。ただし、署名が になるように変更するのは簡単(a -> IO ()) -> IO aです。

物事をより純粋に保ちたい場合は、このアイデアを外にIO出すことなくカプセル化する独自のモナドを作成することをお勧めします。


更新:次のことに注意してください:

例外がすぐに配信されるという保証はありませんが、ランタイムは恣意的な遅延が発生しないように努めます。GHC では、スレッドがセーフ ポイントに到達したときにのみ例外を発生させることができます。セーフ ポイントは、メモリ割り当てが発生する場所です。一部のループは、ループ内でメモリ割り当てを実行しないため、throwTo によって中断することはできません。

( throwToのドキュメントから)。上記の例では、facはメモリを割り当てていないため、大きな数の場合でもすぐに中断されることはありません。

更新:私は、最後の結果を返すかタイムアウトで終了する前に部分的な結果を返すことができる計算のモナドを定義するこれらのアイデアに基づいて、小さなライブラリを作成しました。https://github.com/ppetr/timeout-with-resultsを参照してください

于 2012-12-01T21:55:24.653 に答える
3

探している結果は時間に依存するため、これには必然的に不純なコードが含まれます。

System.Timeoutパッケージからは、タイムアウトまで I/O 計算を実行する機能が提供されているようbaseです (leftaroundabout のコメントによる) IO。 . 注意が必要な部分は、未評価の結果を返すだけでなく、IOアクションが実際に結果を計算するようにすることです。そのためには、からが必要だと思います。evaluateControl.Exception

于 2012-12-01T20:43:38.013 に答える
2

System.Timeout行く方法です。非常にクリーンなインターフェイスを備えているため、スレッドをいじっているような感覚はまったくありません。

ゲームスペースの検索は純粋な計算のように聞こえ、アクションをSystem.Timeout実行IOするため、値をでラップし、WHNFに評価された直後に回答が返されたとすぐに信じられないようreturnに、コードを厳密に評価する必要があります。 timeout

私が抱えていた同様の問題から、コードがどのように見えるかの例がここにあります。

于 2012-12-01T21:48:22.747 に答える