rb_prob 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/examples/alarm.rb +8 -8
- data/examples/diagnosis.rb +12 -11
- data/examples/drugtest.rb +16 -8
- data/examples/spamplan.rb +5 -5
- data/lib/prob.rb +115 -103
- metadata +12 -5
data/examples/alarm.rb
CHANGED
|
@@ -90,7 +90,7 @@ def mk_joint_p(&blk)
|
|
|
90
90
|
p_alarm(b, e).dep {|a|
|
|
91
91
|
p_john(a).dep { |j|
|
|
92
92
|
p_mary(a).dep {|m|
|
|
93
|
-
|
|
93
|
+
mk_const(if blk then blk.call([b,e,a,j,m])
|
|
94
94
|
else [b,e,a,j,m] end)
|
|
95
95
|
}
|
|
96
96
|
}
|
|
@@ -122,7 +122,7 @@ def mk_joint_p2( tsts = {}, &blk )
|
|
|
122
122
|
condition(!tsts[:john] || tsts[:john] == j) {
|
|
123
123
|
p_mary(a).dep {|m|
|
|
124
124
|
condition(!tsts[:mary] || tsts[:mary] == m) {
|
|
125
|
-
|
|
125
|
+
mk_const(if blk then blk.call [b,e,a,j,m] else [b,e,a,j,m] end)
|
|
126
126
|
}}
|
|
127
127
|
}}
|
|
128
128
|
}}
|
|
@@ -133,18 +133,18 @@ end
|
|
|
133
133
|
# like mk_joint_p2, but using event_dep directly instead of mixing in
|
|
134
134
|
# condition-statements
|
|
135
135
|
def mk_joint_p3 (tsts = {}, &blk)
|
|
136
|
-
tst_b =
|
|
137
|
-
tst_e =
|
|
138
|
-
tst_a =
|
|
139
|
-
tst_j =
|
|
140
|
-
tst_m =
|
|
136
|
+
tst_b = if_just tsts[:burglary]
|
|
137
|
+
tst_e = if_just tsts[:earthquake]
|
|
138
|
+
tst_a = if_just tsts[:alarm]
|
|
139
|
+
tst_j = if_just tsts[:john]
|
|
140
|
+
tst_m = if_just tsts[:mary]
|
|
141
141
|
|
|
142
142
|
PBurglary.event_dep(tst_b) {|b|
|
|
143
143
|
PEarthquake.event_dep(tst_e) {|e|
|
|
144
144
|
p_alarm(b,e).event_dep(tst_a) {|a|
|
|
145
145
|
p_john(a).event_dep(tst_j) {|j|
|
|
146
146
|
p_mary(a).event_dep(tst_m) {|m|
|
|
147
|
-
|
|
147
|
+
mk_const(if blk then blk.call [b,e,a,j,m] else [b,e,a,j,m] end)
|
|
148
148
|
}
|
|
149
149
|
}
|
|
150
150
|
}
|
data/examples/diagnosis.rb
CHANGED
|
@@ -52,36 +52,37 @@ end
|
|
|
52
52
|
# P(T|I)
|
|
53
53
|
# but combine states and save final distribution in constant
|
|
54
54
|
PTest = PDisease.dep {|i|
|
|
55
|
-
pTest(i).dep {|t|
|
|
55
|
+
pTest(i).dep {|t| mk_const([i,t]) }
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
testpred = Proc.new {|disease, test| disease == :ILL}
|
|
59
59
|
|
|
60
|
-
|
|
60
|
+
puts "joint probability:"
|
|
61
|
+
puts PTest
|
|
61
62
|
|
|
62
63
|
# using filter we find on PTest which is P(T|I) we find
|
|
63
64
|
# P( I | T = Positive )
|
|
64
|
-
|
|
65
|
-
|
|
65
|
+
puts "probability of I if test is Positive:"
|
|
66
|
+
puts PTest.filter{|disease, test| test == :Positive}
|
|
66
67
|
|
|
67
68
|
# using the testpred function and query we can find the probability of all
|
|
68
69
|
# events testpred returns true for. In this case P( I = Ill | T = Positive)
|
|
69
|
-
|
|
70
|
-
|
|
70
|
+
puts "\nprobability of being ill"
|
|
71
|
+
puts PTest.filter{|disease,test| test == :Positive}.query? &testpred
|
|
71
72
|
|
|
72
73
|
# next find the most probable explanation if Test was Positive:
|
|
73
|
-
|
|
74
|
-
|
|
74
|
+
puts "\nmost probable"
|
|
75
|
+
puts PTest.filter{|disease,test| test == :Positive}.most_probable
|
|
75
76
|
|
|
76
77
|
# alternatively using condition on the monadic computation directly
|
|
77
78
|
# and normalizing the result needed multiplications and memory may be reduced:
|
|
78
79
|
# event_dep is like 'dep {|var| condition(var == :Positive) { ... } }'
|
|
79
|
-
|
|
80
|
-
|
|
80
|
+
puts "\nanother way of finding P(I|T=Positive)"
|
|
81
|
+
puts PDisease.dep {|i|
|
|
81
82
|
# event_dep will execute block only if
|
|
82
83
|
# Test was :Positive and return 'nil' else
|
|
83
84
|
pTest(i).event_dep(just :Positive) {
|
|
84
|
-
|
|
85
|
+
mk_const(i)
|
|
85
86
|
}
|
|
86
87
|
}.normalize
|
|
87
88
|
|
data/examples/drugtest.rb
CHANGED
|
@@ -11,14 +11,14 @@ def drugTest(puser = 0.001, p_posifuser = 0.99, p_posifclean = 0.01)
|
|
|
11
11
|
choose(puser, :User, :Clean).dep { |user|
|
|
12
12
|
choose(if user == :User then p_posifuser else p_posifclean end,
|
|
13
13
|
:Pos, :Neg).dep { |test|
|
|
14
|
-
|
|
14
|
+
mk_const([user, test])
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
def drugTest2
|
|
20
20
|
drugTest.dep {|u,t|
|
|
21
|
-
if t == :Pos then
|
|
21
|
+
if t == :Pos then mk_const(u) else nil end
|
|
22
22
|
}
|
|
23
23
|
end
|
|
24
24
|
|
|
@@ -27,7 +27,7 @@ def drugTest3(puser = 0.001, p_posifuser = 0.99, p_posifclean = 0.01)
|
|
|
27
27
|
choose(if user == :User then p_posifuser else p_posifclean end,
|
|
28
28
|
:Pos, :Neg).dep { |test|
|
|
29
29
|
condition(test == :Pos) {
|
|
30
|
-
|
|
30
|
+
mk_const user
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
}.normalize
|
|
@@ -35,10 +35,18 @@ end
|
|
|
35
35
|
|
|
36
36
|
#p drugTest2
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
p drugTest(0.5).filter {|u,t| t == :Pos}
|
|
38
|
+
puts "test1"
|
|
39
|
+
puts drugTest
|
|
41
40
|
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
puts "\ntest2"
|
|
42
|
+
puts drugTest.filter {|u,t| t == :Pos }
|
|
43
|
+
|
|
44
|
+
puts "\ntest3"
|
|
45
|
+
puts drugTest(0.5).filter {|u,t| t == :Pos}
|
|
46
|
+
|
|
47
|
+
puts "\ntest4"
|
|
48
|
+
puts drugTest3
|
|
49
|
+
|
|
50
|
+
puts "\ntest5"
|
|
51
|
+
puts drugTest3(0.5)
|
|
44
52
|
|
data/examples/spamplan.rb
CHANGED
|
@@ -121,7 +121,7 @@ module SpamDatabaseProbabilities
|
|
|
121
121
|
# P(W|S) <- likelyhood
|
|
122
122
|
|
|
123
123
|
def pMsgType # P(S)
|
|
124
|
-
|
|
124
|
+
enum_dist types, @msgCounts
|
|
125
125
|
end
|
|
126
126
|
|
|
127
127
|
def pWord(word, type) # P(W == word | S == type)
|
|
@@ -134,7 +134,7 @@ module SpamDatabaseProbabilities
|
|
|
134
134
|
def pHasWord(word, prior = pMsgType)
|
|
135
135
|
prior.dep {|t|
|
|
136
136
|
pWord(word, t).event_dep(just true) {
|
|
137
|
-
|
|
137
|
+
mk_const(t)
|
|
138
138
|
}
|
|
139
139
|
}.normalize
|
|
140
140
|
end
|
|
@@ -282,14 +282,14 @@ class SpamClassifier
|
|
|
282
282
|
f.call uniform(@knowledge.types)
|
|
283
283
|
end
|
|
284
284
|
|
|
285
|
-
def score(
|
|
286
|
-
|
|
285
|
+
def score(&blk)
|
|
286
|
+
characteristic(blk).distance uniform(@knowledge.types)
|
|
287
287
|
end
|
|
288
288
|
|
|
289
289
|
def buildClassifiers
|
|
290
290
|
@knowledge.knownWords.each {|w,types|
|
|
291
291
|
s = score {|prior| @knowledge.pHasWord(w,prior)}
|
|
292
|
-
probs =
|
|
292
|
+
probs = @knowledge.pHasWord(w, uniform(S)).adjust_min
|
|
293
293
|
yield w, s, probs
|
|
294
294
|
}
|
|
295
295
|
end
|
data/lib/prob.rb
CHANGED
|
@@ -2,19 +2,17 @@
|
|
|
2
2
|
# The Probably module provides functions and a discrete Distribution class for
|
|
3
3
|
# monadic functional probabilistic programming in ruby.
|
|
4
4
|
|
|
5
|
-
puts 'loading rb_prob'
|
|
6
|
-
|
|
7
5
|
module Probably
|
|
8
6
|
|
|
9
7
|
# simple helper function running a given block with its first argument and
|
|
10
8
|
# returns first argument
|
|
11
|
-
def block1(
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
def block1(value)
|
|
10
|
+
yield value
|
|
11
|
+
value
|
|
14
12
|
end
|
|
15
13
|
|
|
16
14
|
# given a block return a new Proc defined on range [0..1]
|
|
17
|
-
def
|
|
15
|
+
def mk_shape_fn
|
|
18
16
|
proc { |x|
|
|
19
17
|
if x < 0 || x > 1.0 then 0 else yield x end
|
|
20
18
|
}
|
|
@@ -22,10 +20,10 @@ module Probably
|
|
|
22
20
|
|
|
23
21
|
# creates a Proc computing a gaussian distribution
|
|
24
22
|
# in range [0..1] given a mean and deviation
|
|
25
|
-
def
|
|
23
|
+
def normal_dist(mean, dev)
|
|
26
24
|
include Math
|
|
27
25
|
|
|
28
|
-
|
|
26
|
+
mk_shape_fn { |x|
|
|
29
27
|
u = (x - mean) / dev
|
|
30
28
|
exp (-0.5 * u * u) / sqrt(2 * PI)
|
|
31
29
|
}
|
|
@@ -36,23 +34,23 @@ module Probably
|
|
|
36
34
|
include Enumerable
|
|
37
35
|
|
|
38
36
|
protected
|
|
39
|
-
def
|
|
37
|
+
def init_lsts(data, shape)
|
|
40
38
|
@map = Hash.new(0)
|
|
41
39
|
count = data.length
|
|
42
|
-
data.each_with_index { |
|
|
43
|
-
@map[
|
|
40
|
+
data.each_with_index { |value, index|
|
|
41
|
+
@map[value] += shape.call( Float(index + 1) / count )
|
|
44
42
|
}
|
|
45
43
|
end
|
|
46
44
|
|
|
47
|
-
def
|
|
45
|
+
def init_map(map)
|
|
48
46
|
@map = Hash.new(0)
|
|
49
|
-
|
|
50
|
-
self.
|
|
47
|
+
map.each { |value, prob| @map[value] = prob }
|
|
48
|
+
self.normalize_probabilities
|
|
51
49
|
end
|
|
52
50
|
|
|
53
|
-
def
|
|
51
|
+
def normalize_probabilities
|
|
54
52
|
sum = Float( @map.values.inject(:+) )
|
|
55
|
-
@map.keys.each { |
|
|
53
|
+
@map.keys.each { |value| @map[value] /= sum } if sum != 1.0
|
|
56
54
|
end
|
|
57
55
|
|
|
58
56
|
public
|
|
@@ -72,13 +70,13 @@ module Probably
|
|
|
72
70
|
when :MAP
|
|
73
71
|
@map = data[0]
|
|
74
72
|
when :MAPCOPY
|
|
75
|
-
|
|
73
|
+
init_map(data[0])
|
|
76
74
|
when :LISTS
|
|
77
|
-
|
|
75
|
+
init_lsts(data[0], data[1])
|
|
78
76
|
else
|
|
79
77
|
raise "unable to create probability distribution"
|
|
80
78
|
end
|
|
81
|
-
self.
|
|
79
|
+
self.normalize_probabilities
|
|
82
80
|
end
|
|
83
81
|
|
|
84
82
|
# set of keys in distribution
|
|
@@ -92,7 +90,7 @@ module Probably
|
|
|
92
90
|
# to compute normalization of bayes theorem
|
|
93
91
|
def normalize
|
|
94
92
|
if @map[nil] > 0.0
|
|
95
|
-
filter { |
|
|
93
|
+
filter { |value| value != nil }
|
|
96
94
|
else
|
|
97
95
|
@self
|
|
98
96
|
end
|
|
@@ -115,30 +113,36 @@ module Probably
|
|
|
115
113
|
# randomly pick a key-value with respect to its probability
|
|
116
114
|
# in given distribution
|
|
117
115
|
def pick
|
|
118
|
-
|
|
116
|
+
tst = rand
|
|
119
117
|
sum = 0
|
|
120
|
-
|
|
121
|
-
sum +=
|
|
122
|
-
return
|
|
118
|
+
@map.each do |value, prob|
|
|
119
|
+
sum += prob
|
|
120
|
+
return value,prob if tst < sum
|
|
123
121
|
end
|
|
124
122
|
return nil
|
|
125
123
|
end
|
|
126
124
|
|
|
127
125
|
def each
|
|
128
|
-
@map.each { |
|
|
126
|
+
@map.each { |value, prob| yield prob, value }
|
|
129
127
|
end
|
|
130
128
|
|
|
131
129
|
def map
|
|
132
130
|
tmp = Hash.new(0)
|
|
133
|
-
|
|
134
|
-
tmp[yield(
|
|
131
|
+
@map.each do |value, prob|
|
|
132
|
+
tmp[yield(value)] += prob
|
|
135
133
|
end
|
|
136
134
|
Distribution.new(:MAP, tmp)
|
|
137
135
|
end
|
|
138
136
|
|
|
139
137
|
def filter
|
|
140
|
-
Distribution.new :MAP, @map.reject { |
|
|
141
|
-
!(yield
|
|
138
|
+
Distribution.new :MAP, @map.reject { |value,prob|
|
|
139
|
+
!(yield value)
|
|
140
|
+
}
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def reject
|
|
144
|
+
Distribution.new :MAP, @map.reject { |value, prob|
|
|
145
|
+
yield value
|
|
142
146
|
}
|
|
143
147
|
end
|
|
144
148
|
|
|
@@ -152,61 +156,65 @@ module Probably
|
|
|
152
156
|
def join
|
|
153
157
|
tmp = Hash.new(0)
|
|
154
158
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
tmp[
|
|
159
|
+
@map.each do |dist, p1|
|
|
160
|
+
dist.each do |p2, value|
|
|
161
|
+
tmp[value] += p1 * p2
|
|
158
162
|
end
|
|
159
163
|
end
|
|
160
164
|
Distribution.new(:MAP, tmp)
|
|
161
165
|
end
|
|
162
166
|
|
|
163
167
|
def dep
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
168
|
+
Distribution.new :MAP, block1(Hash.new(0)) {|m|
|
|
169
|
+
@map.each do |key, p1|
|
|
170
|
+
tmp = yield key
|
|
171
|
+
if tmp != nil
|
|
172
|
+
tmp.each do |p2, value|
|
|
173
|
+
m[value] += p1 * p2
|
|
174
|
+
end
|
|
175
|
+
else
|
|
176
|
+
m[nil] += p1
|
|
170
177
|
end
|
|
171
178
|
end
|
|
172
|
-
|
|
173
|
-
Distribution.new(:MAP, m)
|
|
179
|
+
}
|
|
174
180
|
end
|
|
175
181
|
|
|
176
182
|
def event_dep(pred)
|
|
177
|
-
self.dep {|
|
|
178
|
-
if !pred.call
|
|
179
|
-
|
|
183
|
+
self.dep {|value|
|
|
184
|
+
if !pred.call value
|
|
185
|
+
nil
|
|
180
186
|
else
|
|
181
|
-
yield
|
|
187
|
+
yield value
|
|
182
188
|
end
|
|
183
189
|
}
|
|
184
190
|
end
|
|
185
191
|
|
|
186
192
|
def mult(dist2)
|
|
187
193
|
self.dep do |k|
|
|
188
|
-
if block_given?
|
|
189
|
-
|
|
194
|
+
if block_given?
|
|
195
|
+
dist2.map { |k2| yield(k, k2) }
|
|
196
|
+
else
|
|
197
|
+
dist2.map { |k2| [k, k2] }
|
|
190
198
|
end
|
|
191
199
|
end
|
|
192
200
|
end
|
|
193
201
|
|
|
194
|
-
def * (
|
|
195
|
-
self.mult
|
|
202
|
+
def * (other)
|
|
203
|
+
self.mult other
|
|
196
204
|
end
|
|
197
205
|
|
|
198
206
|
# computes expectation given that keys in distribution
|
|
199
207
|
# are numeric
|
|
200
208
|
def expectation
|
|
201
|
-
@map.reduce(0) {|sum, (
|
|
209
|
+
@map.reduce(0) {|sum, (value, p)| sum + value.to_f * p }
|
|
202
210
|
end
|
|
203
211
|
|
|
204
212
|
# computes variance given that keys in distribution
|
|
205
213
|
# are numeric
|
|
206
214
|
def variance
|
|
207
215
|
expected = self.expectation
|
|
208
|
-
@map.reduce(0) {|sum, (
|
|
209
|
-
tmp = (
|
|
216
|
+
@map.reduce(0) {|sum, (value,p)|
|
|
217
|
+
tmp = (value.to_f - expectation)
|
|
210
218
|
sum + tmp * tmp * p
|
|
211
219
|
}
|
|
212
220
|
end
|
|
@@ -218,110 +226,114 @@ module Probably
|
|
|
218
226
|
end
|
|
219
227
|
|
|
220
228
|
def to_s
|
|
221
|
-
@map.reduce("") { |str,(
|
|
222
|
-
str + "#{
|
|
229
|
+
@map.reduce("") { |str,(value, prob)|
|
|
230
|
+
str + "#{value} : #{prob * 100} %\n"
|
|
223
231
|
}
|
|
224
232
|
end
|
|
233
|
+
|
|
234
|
+
def distance(other)
|
|
235
|
+
(self.keys | other.keys).reduce(0) {|sum, value|
|
|
236
|
+
tmp = self.probability(value) - other.probability(value)
|
|
237
|
+
sum + tmp * tmp
|
|
238
|
+
}
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def adjust_min(new_min = 0.01)
|
|
242
|
+
tmp = Hash.new(0)
|
|
243
|
+
self.each do |prob, value|
|
|
244
|
+
tmp[value] = if prob > new_min then prob else new_min end
|
|
245
|
+
end
|
|
246
|
+
Distribution.new :MAP, tmp
|
|
247
|
+
end
|
|
225
248
|
end
|
|
226
249
|
|
|
227
250
|
# create uniformly distributed Distribution from array of values
|
|
228
251
|
def uniform(data)
|
|
229
|
-
Distribution.new :LISTS, data,
|
|
252
|
+
Distribution.new :LISTS, data, mk_shape_fn {|x| 1}
|
|
230
253
|
end
|
|
231
254
|
|
|
232
255
|
# creates linearly distributed Distribution from array of values
|
|
233
256
|
def linear(data)
|
|
234
|
-
Distribution.new :LISTS, data,
|
|
257
|
+
Distribution.new :LISTS, data, mk_shape_fn {|x| x }
|
|
235
258
|
end
|
|
236
259
|
|
|
237
260
|
# creates exp(-x) distributed Distribution from array of values
|
|
238
|
-
def
|
|
239
|
-
Distribution.new :LISTS, data,
|
|
261
|
+
def nexp(data)
|
|
262
|
+
Distribution.new :LISTS, data, mk_shape_fn {|x| Math.exp(-x) }
|
|
240
263
|
end
|
|
241
264
|
|
|
242
265
|
# creates Distribution from array of values using a gaussian distribution
|
|
243
266
|
def normal(data, mean = 0.5, dev = 0.5)
|
|
244
|
-
Distribution.new :LISTS, data,
|
|
267
|
+
Distribution.new :LISTS, data, normal_dist(mean, dev)
|
|
245
268
|
end
|
|
246
269
|
|
|
247
270
|
# creates a distribution from first array holding the distribution
|
|
248
271
|
# values and second one the corresponding probabilities (do be normalized)
|
|
249
272
|
# - data: array of input values
|
|
250
273
|
# - dist: array of probabilities
|
|
251
|
-
def
|
|
252
|
-
|
|
274
|
+
def enum_dist(data, dist)
|
|
275
|
+
dist_len = dist.length
|
|
276
|
+
|
|
277
|
+
if data.length != dist_len
|
|
253
278
|
raise "data and distribution length must be equal"
|
|
254
279
|
end
|
|
255
280
|
|
|
256
|
-
Distribution.new :LISTS, data,
|
|
281
|
+
Distribution.new :LISTS, data, mk_shape_fn {|i|
|
|
282
|
+
dist[i * dist_len - 1]
|
|
283
|
+
}
|
|
257
284
|
end
|
|
258
285
|
|
|
259
286
|
# Creates a new probability distribution from given map:
|
|
260
287
|
# m = { key1 => probability1, key2 => probability2, key3 => ... }
|
|
261
|
-
def
|
|
288
|
+
def dist_from_map(m)
|
|
262
289
|
Distribution.new :MAPCOPY, m
|
|
263
290
|
end
|
|
264
291
|
|
|
265
|
-
def
|
|
266
|
-
Distribution.new :LISTS, data,
|
|
292
|
+
def dist_with(data, &blk)
|
|
293
|
+
Distribution.new :LISTS, data, mk_shape_fn(&blk)
|
|
267
294
|
end
|
|
268
295
|
|
|
269
|
-
def choose(
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
296
|
+
def choose(prob, value, other)
|
|
297
|
+
Distribution.new :MAP, block1(Hash.new(0)) { |tmp|
|
|
298
|
+
tmp[value] = prob
|
|
299
|
+
tmp[other] = 1 - prob
|
|
300
|
+
}
|
|
274
301
|
end
|
|
275
302
|
|
|
276
|
-
def
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
303
|
+
def mk_const(value)
|
|
304
|
+
Distribution.new :MAP, block1(Hash.new(0)) { |tmp|
|
|
305
|
+
tmp[value] = 1
|
|
306
|
+
}
|
|
280
307
|
end
|
|
281
308
|
|
|
282
|
-
def histogram(
|
|
283
|
-
block1(Hash.new(0)) do |
|
|
284
|
-
|
|
285
|
-
|
|
309
|
+
def histogram(iter)
|
|
310
|
+
block1(Hash.new(0)) do |tmp|
|
|
311
|
+
iter.each do |value|
|
|
312
|
+
tmp[value] += 1
|
|
286
313
|
end
|
|
287
314
|
end
|
|
288
315
|
end
|
|
289
316
|
|
|
290
|
-
def condition(
|
|
291
|
-
if
|
|
317
|
+
def condition(bool)
|
|
318
|
+
if bool then yield else nil end
|
|
292
319
|
end
|
|
293
320
|
|
|
294
321
|
# events
|
|
295
|
-
def
|
|
296
|
-
|
|
322
|
+
def mk_event(&fn)
|
|
323
|
+
fn
|
|
297
324
|
end
|
|
298
325
|
|
|
299
|
-
def just(
|
|
300
|
-
|
|
326
|
+
def just(default)
|
|
327
|
+
mk_event {|value| default == value}
|
|
301
328
|
end
|
|
302
329
|
|
|
303
|
-
def
|
|
304
|
-
if
|
|
305
|
-
else proc {|
|
|
330
|
+
def if_just(default)
|
|
331
|
+
if default == nil then proc {|value| true }
|
|
332
|
+
else proc {|value| default == value } end
|
|
306
333
|
end
|
|
307
334
|
|
|
308
|
-
def
|
|
309
|
-
proc {|
|
|
310
|
-
end
|
|
311
|
-
|
|
312
|
-
def pDistance(dist1, dist2)
|
|
313
|
-
(dist1.keys | dist2.keys).reduce(0) {|sum,k|
|
|
314
|
-
tmp = dist1.probability(k) - dist2.probability(k)
|
|
315
|
-
sum + tmp * tmp
|
|
316
|
-
}
|
|
317
|
-
end
|
|
318
|
-
|
|
319
|
-
def adjustMinimums(dist, newMin = 0.01)
|
|
320
|
-
tmp = Hash.new(0)
|
|
321
|
-
dist.each do |p,k|
|
|
322
|
-
tmp[k] = if p > newMin then p else newMin end
|
|
323
|
-
end
|
|
324
|
-
Distribution.new :MAP, tmp
|
|
335
|
+
def one_of(*elems)
|
|
336
|
+
proc {|value| elems.include? value }
|
|
325
337
|
end
|
|
326
338
|
|
|
327
339
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rb_prob
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
|
|
4
|
+
prerelease: false
|
|
5
|
+
segments:
|
|
6
|
+
- 0
|
|
7
|
+
- 0
|
|
8
|
+
- 2
|
|
9
|
+
version: 0.0.2
|
|
5
10
|
platform: ruby
|
|
6
11
|
authors:
|
|
7
12
|
- Steffen Siering
|
|
@@ -9,7 +14,7 @@ autorequire:
|
|
|
9
14
|
bindir: bin
|
|
10
15
|
cert_chain: []
|
|
11
16
|
|
|
12
|
-
date: 2010-03-
|
|
17
|
+
date: 2010-03-24 00:00:00 +01:00
|
|
13
18
|
default_executable:
|
|
14
19
|
dependencies: []
|
|
15
20
|
|
|
@@ -42,18 +47,20 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
42
47
|
requirements:
|
|
43
48
|
- - ">="
|
|
44
49
|
- !ruby/object:Gem::Version
|
|
50
|
+
segments:
|
|
51
|
+
- 0
|
|
45
52
|
version: "0"
|
|
46
|
-
version:
|
|
47
53
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
48
54
|
requirements:
|
|
49
55
|
- - ">="
|
|
50
56
|
- !ruby/object:Gem::Version
|
|
57
|
+
segments:
|
|
58
|
+
- 0
|
|
51
59
|
version: "0"
|
|
52
|
-
version:
|
|
53
60
|
requirements: []
|
|
54
61
|
|
|
55
62
|
rubyforge_project:
|
|
56
|
-
rubygems_version: 1.3.
|
|
63
|
+
rubygems_version: 1.3.6
|
|
57
64
|
signing_key:
|
|
58
65
|
specification_version: 3
|
|
59
66
|
summary: monadic probabilistic programming for ruby
|