Subscribed unsubscribe Subscribe Subscribe

2次元random walk

Haskell

前のエントリを2次元に拡張したもの。

1次元版ではコインの表裏を+1/-1に対応させていたが、今回は方角、つまり東西南北を縦軸と横軸に対応させる。実験では平面上に100万ステップ分をプロットしている。

するとこんな図や、

こんな図になる。おもしろい。

以下コード。

今回は一本のランダムウォークのみなので乱数生成器を引き回す必要がないため、Stateモナドを使っていない。関数適用((->) r)はMonadインスタンスになっているので、Rand aをStdGen -> aとすることで、randomWalk関数はそのまま流用することができている。

import Control.Applicative hiding (empty)
import Graphics.Rendering.Diagrams
import Graphics.Rendering.Diagrams.Types
import System.Random

data Bearing = North | East | West | South deriving (Eq, Enum, Bounded, Show)

instance Random Bearing where
  randomR (a, b) g = let (x, g') = randomR (fromEnum a, fromEnum b) g
                     in  (toEnum x, g')
  random g         = randomR (minBound, maxBound) g

type Rand a = StdGen -> a

bearings :: Rand [Bearing]
bearings = randoms

plot :: [Bearing] -> [Vec]
plot = map go
  where go North = ( 0, -1)
        go East  = ( 1,  0)
        go West  = (-1,  0)
        go South = ( 0,  1)

randomWalk :: Rand Diagram
randomWalk = do
  bs <- plot <$> bearings
  return $ straight $ pathFromVectors (take 1000000 bs)

main :: IO ()
main = randomWalk <$> getStdGen >>=
       renderAs PNG "random-walk-2d.png" Auto