public
Description: various code snippets in various languages
Homepage: http://spotless-spots.blogspot.com
Clone URL: git://github.com/namin/spots.git
olpc (author)
Wed Mar 18 16:31:04 -0700 2009
commit  fb5d7f36a7a5a302e3f2dd3086faeffa1763716f
tree    053d01820de7456e771a65062d11992ac007412e
parent  266a015ff090cea119e4356eae0cba32be6b02d1
spots / probabilisticModeling / probabilisticModeling.hs
100644 137 lines (107 sloc) 4.36 kb
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import System.Random
import Data.Set (Set)
import qualified Data.Set as Set
 
data Sample a =
    Sample (IO a)
 
data Support a =
    Support ([a])
 
data Expectation a =
    Expectation ((a -> Double) -> Double)
 
data Distribution a =
    Distribution (Sample a) (Support a) (Expectation a)
 
always x =
    Distribution (Sample sample) (Support support) (Expectation expectation)
    where sample = return x
          support = [x]
          expectation h = h(x)
 
rnd :: IO Double
rnd = getStdRandom (randomR (0.0,1.0))
 
coinFlip p
         (Distribution (Sample sample1) (Support support1) (Expectation expectation1))
         (Distribution (Sample sample2) (Support support2) (Expectation expectation2)) =
    Distribution (Sample sample) (Support support) (Expectation expectation)
    where sample = do rndProb <- rnd; if rndProb < p then sample1 else sample2
          support = support1 ++ support2
          expectation h = p * expectation1(h) + (1.0-p) * expectation2(h)
 
distSample (Distribution (Sample sample) (Support support) (Expectation expectation)) = sample
distSupport (Distribution (Sample sample) (Support support) (Expectation expectation)) = support
distExpectation (Distribution (Sample sample) (Support support) (Expectation expectation)) = expectation
 
(|>) x f = f x
 
bind dist k =
    Distribution (Sample sample) (Support support) (Expectation expectation)
    where sample = do d <- dist |> distSample; k d |> distSample
          support = dist |> distSupport |> concatMap (\d -> (k d) |> distSupport)
          expectation h = (dist |> distExpectation)(\x -> ((k x) |> distExpectation)(h))
 
distWithCleanSupport (Distribution s (Support support) e) =
    Distribution s (Support support') e
    where support' = support |> Set.fromList |> Set.toList
 
instance Monad Distribution where
    (>>=) = bind
    return = always
 
weightedCases inp =
    coinFlips 0.0 inp
    where coinFlips w l =
              case l of
                [] -> error "no coinFlips"
                [(d,_)] -> always d
                (d,p):rest -> coinFlip (p/(1.0-w)) (always d) (coinFlips (w+p) rest)
 
countedCases inp =
    weightedCases (inp |> map (\(x,v) -> (x,v/total)))
    where total = 1.0*(inp |> map (\(_,v) -> v) |> sum)
 
data Outcome = Even | Odd | Zero deriving (Show,Eq,Ord)
 
roulette = countedCases [(Even,18),(Odd,18),(Zero,1)]
 
printSample d =
    do r <- distSample d
       putStrLn $ show $ r
 
printExpectation d h =
    putStrLn $ show $ (distExpectation d) h
 
data Light = Red | Green | Yellow deriving (Show,Eq,Ord)
 
trafficLightD = weightedCases [(Red,0.50),(Yellow,0.10),(Green,0.40)]
 
data Action = Stop | Drive deriving (Show,Eq,Ord)
 
cautiousDriver light =
    case light of
      Red -> always Stop
      Yellow -> weightedCases [(Stop,0.9),(Drive,0.1)]
      Green -> always Drive
 
aggressiveDriver light =
    case light of
      Red -> weightedCases [(Stop,0.9),(Drive,0.1)]
      Yellow -> weightedCases [(Stop,0.1),(Drive,0.9)]
      Green -> always Drive
 
otherLight light =
    case light of
      Red -> Green
      Yellow -> Red
      Green -> Red
 
data CrashResult = Crash | NoCrash deriving (Show,Eq,Ord)
 
crash driverOneD driverTwoD lightD =
    do light <- lightD
       driverOne <- driverOneD light
       driverTwo <- driverTwoD (otherLight light)
       case (driverOne,driverTwo) of
         (Drive,Drive) -> weightedCases [(Crash,0.9),(NoCrash,0.1)]
         _ -> return NoCrash
 
model = crash cautiousDriver aggressiveDriver trafficLightD
 
model2 = crash aggressiveDriver aggressiveDriver trafficLightD
 
main =
    do printSample roulette
       -- Odd
       printSample roulette
       -- Even
       printExpectation roulette (\x -> case x of
                                          Even -> 10.0
                                          Odd -> 0.0
                                          Zero -> 0.0)
       -- 4.864864864864865
       printSample model
       -- NoCrash
       printSample model
       -- NoCrash
       printExpectation model (\x -> case x of
                                       Crash -> 1.0
                                       NoCrash -> 0.0)
       -- 0.036899999999999995
       printExpectation model2 (\x -> case x of
                                        Crash -> 1.0
                                        NoCrash -> 0.0)
       -- 0.08909999999999998