-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathIrmTest.hs
122 lines (95 loc) · 4.13 KB
/
IrmTest.hs
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
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeSynonymInstances #-}
module IrmTest where
import LazyPPL.Distributions
import LazyPPL.Distributions.DirichletP
import LazyPPL.Distributions.Memoization
import LazyPPL
instance (MonadMemo Prob String) where memoize = generalmemoize
type Person = String
-- | Simple Infinite Relational Model Example from Web Church / Prob Mods
-- | A Chinese Restaurant, where tables are social groups
example :: Meas (Bool, Bool)
example = do
r :: Restaurant <- sample $ newRestaurant 1.0
-- Chance of people at 'tableA' talking to people at 'tableB'
near :: ((Table, Table) -> Double) <- sample $ memoize $ \(tableA, tableB) -> beta 0.5 0.5
-- Assign a table to each person
table :: (Person -> Table) <- sample $ memoize $ \person -> newCustomer r
-- function to observe that personA talks to person B
let talks :: (Person, Person) -> Meas () = \(personA, personB) -> score $ near (table personA, table personB)
-- function to observe that personA doesn't talk to person B
let nottalks :: (Person, Person) -> Meas () = \(personA, personB) -> score $ 1 - near (table personA, table personB)
-- Data set
mapM_ talks [("tom", "fred"), ("tom", "jim"), ("jim", "fred"), ("mary", "sue"), ("mary", "ann"), ("ann", "sue")]
mapM_ nottalks [("mary", "fred"), ("mary", "jim"), ("sue", "fred"), ("sue", "tom"), ("ann", "jim"), ("ann", "tom")]
-- We want to know whether Tom and Fred are at the same table,
-- and whether Tom and Mary are at the same table.
return (table "tom" == table "fred", table "tom" == table "mary")
test = do
bcws <- mh 0.2 example
let bcs = map fst $ take 100 . every 1000 . drop 10000 $ bcws
print $ fromIntegral (length $ filter fst bcs) / fromIntegral (length bcs)
print $ fromIntegral (length $ filter snd bcs) / fromIntegral (length bcs)
main = test
{-- Web Church Program from http://v1.probmods.org/non-parametric-models.html#example-the-infinite-relational-model
Seems to return the wrong result: Says ~35% chance of Tom and Mary in the same group.
(define samples
(mh-query
300 10000
(define class-distribution (DPmem 1.0 gensym))
(define object->class
(mem (lambda (object) (class-distribution))))
(define classes->parameters
(mem (lambda (class1 class2) (beta 0.5 0.5))))
(define (talks object1 object2)
(flip (classes->parameters (object->class object1) (object->class object2))))
(list (equal? (object->class 'tom) (object->class 'fred))
(equal? (object->class 'tom) (object->class 'mary)))
(and (talks 'tom 'fred)
(talks 'tom 'jim)
(talks 'jim 'fred)
(not (talks 'mary 'fred))
(not (talks 'mary 'jim))
(not (talks 'sue 'fred))
(not (talks 'sue 'tom))
(not (talks 'ann 'jim))
(not (talks 'ann 'tom))
(talks 'mary 'sue)
(talks 'mary 'ann)
(talks 'ann 'sue)
)))
(hist (map first samples) "tom and fred in same group?")
(hist (map second samples) "tom and mary in same group?")
--}
{-- Rejection sampler in Web Church for validation
This returns the same results as LazyPPL mh.
(define (samples)
(rejection-query
(define class-distribution (DPmem 1.0 gensym))
(define object->class
(mem (lambda (object) (class-distribution))))
(define classes->parameters
(mem (lambda (class1 class2) (beta 0.5 0.5))))
(define (talks object1 object2)
(flip (classes->parameters (object->class object1) (object->class object2))))
(list (equal? (object->class 'tom) (object->class 'fred))
(equal? (object->class 'tom) (object->class 'mary)))
(and (talks 'tom 'fred)
(talks 'tom 'jim)
(talks 'jim 'fred)
(not (talks 'mary 'fred))
(not (talks 'mary 'jim))
(not (talks 'sue 'fred))
(not (talks 'sue 'tom))
(not (talks 'ann 'jim))
(not (talks 'ann 'tom))
(talks 'mary 'sue)
(talks 'mary 'ann)
(talks 'ann 'sue)
)))
(hist (map first (repeat 200 samples)) "tom and mary in same group?")
(hist (map second (repeat 200 samples)) "tom and mary in same group?")
--}