0votos

Simulación de llegada de carros en Haskell

por josejuan hace 3 años

Hecho con el único propósito de obtener el resultado esperado (no parametrizado, etc...).

Simularan llegada de carros, y se cuentan con 4 estacionamientos libres.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
{-# LANGUAGE RecordWildCards #-} 
{-# LANGUAGE FlexibleContexts #-} 
import qualified Data.Heap as H -- por comodidad y eficiencia 
import System.Random 
import Control.Monad 
 
-- para la simulación, usaremos pasos de "a minuto", lo ideal sería tomar 
-- valores lo más pequeños posibles pero nos veríamos afectados tanto por 
-- un mayor número de operaciones como por errores de precisión (pues las 
-- probabilidades de sucesos >0 serán todavía mucho menores) 
entrenKcochesEnCiertoMinuto :: Int -> Double 
entrenKcochesEnCiertoMinuto q = (m**k * exp (-m)) / product [2..k] 
  where m = 35/60 
        k = fromIntegral q 
 
-- la tabla de probabilidades (para este experimento concreto) queda memoizada 
tablaPAcum :: [(Int, Double)] 
tablaPAcum = tail $ iterate (\(i, s) -> (i + 1, s + entrenKcochesEnCiertoMinuto (i + 1))) (-1, 0) 
 
-- dada una P dice cuantos coches entran en un minuto dado 
entranSegunP :: Double -> Int 
entranSegunP p = fst $ head $ dropWhile ((<p).snd) tablaPAcum 
 
-- el estado de nuestra simulación 
data Estado = Estado { minutoReloj :: Int     -- nuestro reloj (o paso de simulación) 
                     , plazas      :: H.MinHeap Int -- el estado de las plazas de parking 
                                                    -- <  0 si la plaza está libre 
                                                    -- >= 0 es el minuto en que se libera 
                     , cochesKo    :: Int     -- total de coches que no han aparcado 
                     , cochesOk    :: Int     -- total de doches que sí han aparcado 
                     } deriving Show 
 
simulación (Estado {..}) = do 
  -- mostramos estado de la simulación (o devolvemos resultado o lo que sea) 
  when (minutoReloj `mod` 1000 == 0) $ putStrLn $ "Minuto: " ++ show minutoReloj ++ "\nCon plaza: " ++ show cochesOk ++ "\nSin plaza: " ++ show cochesKo ++ "\n\n" 
  let minuto = minutoReloj + 1          -- nuevo minuto: tic, tac, tic, ... 
      plazas' = se_van plazas           -- quitamos los coches que se van 
      se_van p = maybe p (\t -> if t <= minuto then se_van (H.drop 1 p) else p) (H.viewHead p) 
  llegan <- entranSegunP <$> randomRIO (0, 1) 
  estado' <- llega_vehículos llegan $ Estado minuto plazas' cochesKo cochesOk 
  simulación estado' 
 
llega_vehículos 0 e = return e 
llega_vehículos n (Estado {..}) = 
  if H.size plazas >= 4 
     then return $ Estado minutoReloj plazas (cochesKo + n) cochesOk 
     else do m <- (minutoReloj +) <$> randomRIO (5, 10) 
             llega_vehículos (n - 1) $ Estado minutoReloj (H.insert m plazas) cochesKo (cochesOk + 1) 
 
{- 
 
... 
 
Minuto: 405000 
Con plaza: 160383 
Sin plaza: 75847 
 
 
Minuto: 406000 
Con plaza: 160787 
Sin plaza: 76055 
 
 
Minuto: 407000 
Con plaza: 161187 
Sin plaza: 76276 
 
 
Minuto: 408000 
Con plaza: 161571 
Sin plaza: 76477 
 
 
Minuto: 409000 
Con plaza: 161955 
Sin plaza: 76652 
 
... 
 
-} 

Comenta la solución

Tienes que identificarte para poder publicar tu comentario.