rl-satton-0.1.2.4: examples/Examples/Ch4_GridWorld/Rules.hs
{-|
Satton, 'Reinforcement Learning: The Introduction', pg.86, Example 4.1: GridWorld
-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
module Examples.Ch4_GridWorld.Rules where
import qualified Data.List as List
import qualified Data.Map.Strict as Map
import qualified Data.Set as Set
import RL.Types
import RL.Imports
import RL.DP
type Point = (Int,Int)
data Action = L | R | U | D
deriving(Show, Eq, Ord, Enum, Bounded, Generic, Hashable)
data GW num = GW {
gw_size :: (Int,Int),
gw_exits :: Set (Int,Int)
} deriving(Show)
showAction :: Action -> String
showAction a =
case a of
L->"<"
R->">"
U->"^"
D->"v"
showActions :: Set Action -> String
showActions = concat . map showAction . List.sort . Set.toList
states :: GW num -> Set Point
states (GW (sx,sy) _) = Set.fromList [(x,y) | x <- [0..sx-1], y <- [0..sy-1]]
actions :: GW num -> Point -> Set Action
actions (GW (sx,sy) exits) s =
case Set.member s exits of
True -> Set.empty
False -> Set.fromList [minBound..maxBound]
transition :: GW num -> Point -> Action -> Point
transition (GW (sx,sy) exits) (x,y) a =
let
check (x',y') =
if x' >= 0 && x' < sx && y' >= 0 && y' < sy then
(x',y')
else
(x,y)
in
case a of
L -> check (x-1,y)
R -> check (x+1,y)
U -> check (x,y-1)
D -> check (x,y+1)
showV :: (MonadIO m, Real num) => GW num -> [(Point, num)] -> m ()
showV (GW (sx,sy) _) v = liftIO $ do
forM_ [0..sy-1] $ \y -> do
forM_ [0..sx-1] $ \x -> do
case List.lookup (x,y) v of
Just v -> do
printf "%-2.3f " ((fromRational $ toRational v) :: Double)
Nothing -> do
printf " ? "
printf "\n"
-- TODO: remove recursion
arbitraryState :: MonadRnd g m => GW t -> m Point
arbitraryState gw@GW{..} = do
let (sx,sy) = gw_size
x <- getRndR (0,sx-1)
y <- getRndR (0,sy-1)
case isTerminal gw (x,y) of
True -> arbitraryState gw
False -> return (x,y)
isTerminal :: GW num -> Point -> Bool
isTerminal GW{..} p = p `Set.member` gw_exits
withLearnPlot :: Show a => a -> (PlotData -> IO b) -> IO b
withLearnPlot cnt f = do
d <- newData "learnRate"
withPlot "plot1" [heredoc|
set grid back ls 102
set xrange [0:${show cnt}]
set yrange [-20:20]
set terminal x11 1 noraise
done = 0
bind all 'd' 'done = 1'
while(!done) {
plot ${dat d} using 1:2 with lines
pause 1
}
|] (f d)