J'essaie de résoudre le problème 2.8 du livre "AI - A Modern Approach" qui implique une grille de cellules et le choix de mouvements aléatoires pour naviguer dans la grille.
2.7 Mettre en place un environnement pour une pièce rectangulaire n X m, où chaque carré a 5 % de chances de contenir de la saleté et où n et m sont des nombres entiers. carré a 5 % de chances de contenir de la saleté, et n et m sont choisis au aléatoirement entre 8 et 15 inclus.
2.8 Concevoir et mettre en œuvre un agent réflexe pur pour l'environnement de l'exercice 2.7. l'exercice 2.7, sans tenir compte de l'obligation de rentrer chez soi, et mesurez ses ses performances.
J'ai donc utilisé deux monades d'état - une avec Grid
comme état et un autre avec StdGen
comme l'État. Le code se compile sans aucune erreur mais lorsque je l'exécute depuis GHCi, il se bloque et ne revient pas.
La partie pertinente du code :
Code de soutien
type RandomState = State StdGen
makeGrid :: (Int, Int) -> (Int, Int) -> Float -> RandomState Grid
doAction :: Action -> Cleaner -> State Grid Cleaner
getRandomR :: Random a => (a, a) -> RandomState a
getRandomR limits = do
gen <- get
let (val, gen') = randomR limits gen
put gen'
return val
chooseAction :: Percepts -> RandomState Action
chooseAction percepts
| PhotoSensor `elem` percepts = return SuckDirt
| InfraredSensor `elem` percepts = return TurnOff
| TouchSensor `elem` percepts = return TurnLeft
| otherwise = do
r <- getRandomR ((1, 3) :: (Int, Int))
case r of
1 -> return GoForward
2 -> return TurnRight
3 -> return TurnLeft
Code principal
runCleaner :: Int -> Cleaner -> StateT Grid RandomState Cleaner
runCleaner turnsLeft cleaner@(Cleaner _ _ _ ph _) =
if turnsLeft == 0
then return cleaner
else do
grid <- get
gen <- lift $ get
cleaner <- case ph of
[] -> do
let (cleaner, grid) = runState (doAction GoForward cleaner) grid
put grid
return cleaner
_ -> do
let (action, gen) = runState (chooseAction (head ph)) gen
lift $ put gen
let (cleaner, grid) = runState (doAction action cleaner) grid
put grid
return cleaner
case clState cleaner of
Off -> return cleaner
On -> runCleaner (turnsLeft - 1) cleaner
simulateOnGrid :: Int -> Grid -> StdGen -> (Cleaner, Grid)
simulateOnGrid maxTurns grid gen =
evalState (runStateT (runCleaner maxTurns cleaner) grid) gen
where cleaner = createCleaner (fromJust $ cell (0,0) grid) East
J'invoque le simulateOnGrid
de GHCi comme ceci :
> gen <- newStdGen
> let grid = evalState (makeGrid (8,15) (8,15) 0.05) gen
> simulateOnGrid 5 grid gen
et le code reste bloqué à la ligne :
let (cleaner, grid) = runState (doAction GoForward cleaner) grid
ce que j'ai confirmé en mettant des traces dans le code. L'appel au doAction
ne se produit jamais.
Le problème semble être l'utilisation de runState
à l'intérieur de la runCleaner
mais je ne parviens pas à en trouver la raison.
Veuillez expliquer la raison et s'il existe un moyen de résoudre ce problème.
De même, l'utilisation de runState
à l'intérieur d'une fonction monadique me semble erronée. Veuillez suggérer s'il y a une meilleure façon de le faire.