sbn 0.9.0
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/README +320 -0
- data/lib/combination.rb +78 -0
- data/lib/formats.rb +119 -0
- data/lib/helpers.rb +140 -0
- data/lib/inference.rb +65 -0
- data/lib/learning.rb +141 -0
- data/lib/net.rb +49 -0
- data/lib/numeric_variable.rb +94 -0
- data/lib/sbn.rb +6 -0
- data/lib/string_variable.rb +176 -0
- data/lib/variable.rb +224 -0
- data/test/sbn.rb +5 -0
- data/test/test_combination.rb +51 -0
- data/test/test_helpers.rb +80 -0
- data/test/test_learning.rb +104 -0
- data/test/test_net.rb +136 -0
- data/test/test_variable.rb +373 -0
- metadata +63 -0
@@ -0,0 +1,373 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require File.dirname(__FILE__) + '/../lib/sbn'
|
3
|
+
|
4
|
+
class TestVariable < Test::Unit::TestCase # :nodoc:
|
5
|
+
def setup
|
6
|
+
@net = Sbn::Net.new
|
7
|
+
@var1 = Sbn::Variable.new(@net, "var1")
|
8
|
+
@var2 = Sbn::Variable.new(@net, "var2")
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_add_child
|
12
|
+
assert !@var1.children.include?(@var2)
|
13
|
+
@var1.add_child(@var2)
|
14
|
+
assert @var1.children.include?(@var2)
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_add_child_no_recurse
|
18
|
+
# variable shouldn't be able to add itself as a child
|
19
|
+
children_before = @var1.children.dup
|
20
|
+
@var1.add_child_no_recurse(@var1)
|
21
|
+
children_after = @var1.children.dup
|
22
|
+
assert_equal children_before, children_after
|
23
|
+
|
24
|
+
# add child normally
|
25
|
+
children_before = @var1.children.dup
|
26
|
+
@var1.add_child_no_recurse(@var2)
|
27
|
+
children_after = @var1.children.dup
|
28
|
+
assert_not_equal children_before, children_after
|
29
|
+
assert children_after.include?(@var2)
|
30
|
+
|
31
|
+
# variable shouldn't be able to add same child twice
|
32
|
+
children_before = @var1.children.dup
|
33
|
+
@var1.add_child_no_recurse(@var2)
|
34
|
+
children_after = @var1.children.dup
|
35
|
+
assert_equal children_before, children_after
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_add_parent
|
39
|
+
assert !@var1.parents.include?(@var2)
|
40
|
+
@var1.add_parent(@var2)
|
41
|
+
assert @var1.parents.include?(@var2)
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_add_parent_no_recurse
|
45
|
+
# variable shouldn't be able to add itself as a parent
|
46
|
+
parents_before = @var1.parents.dup
|
47
|
+
@var1.add_parent_no_recurse(@var1)
|
48
|
+
parents_after = @var1.parents.dup
|
49
|
+
assert_equal parents_before, parents_after
|
50
|
+
|
51
|
+
# add parent normally
|
52
|
+
parents_before = @var1.parents.dup
|
53
|
+
@var1.add_parent_no_recurse(@var2)
|
54
|
+
parents_after = @var1.parents.dup
|
55
|
+
assert_not_equal parents_before, parents_after
|
56
|
+
assert parents_after.include?(@var2)
|
57
|
+
|
58
|
+
# variable shouldn't be able to add same parent twice
|
59
|
+
parents_before = @var1.parents.dup
|
60
|
+
@var1.add_parent_no_recurse(@var2)
|
61
|
+
parents_after = @var1.parents.dup
|
62
|
+
assert_equal parents_before, parents_after
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_to_s
|
66
|
+
assert_equal "#{@var1.name}", "#{@var1}"
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_equality
|
70
|
+
assert_equal(@var1, @var1.dup)
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_can_be_evaluated_eh
|
74
|
+
@var1.add_child(@var2)
|
75
|
+
assert @var1.can_be_evaluated?({})
|
76
|
+
assert !@var2.can_be_evaluated?({})
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_children
|
80
|
+
assert @var1.children.class == Array and @var1.children.empty?
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_evaluate_marginal
|
84
|
+
assert_equal @var1.evaluate_marginal(:true, {}), 0.5
|
85
|
+
assert_equal @var1.evaluate_marginal(:false, {}), 0.5
|
86
|
+
|
87
|
+
@var1.add_child(@var2)
|
88
|
+
@var2.set_probabilities([0.25, 0.75, 0.2, 0.8])
|
89
|
+
assert_equal @var2.evaluate_marginal(:true, {:var1 => :true}), 0.25
|
90
|
+
assert_equal @var2.evaluate_marginal(:false, {:var1 => :true}), 0.75
|
91
|
+
assert_equal @var2.evaluate_marginal(:true, {:var1 => :false}), 0.2
|
92
|
+
assert_equal @var2.evaluate_marginal(:false, {:var1 => :false}), 0.8
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_evidence_name
|
96
|
+
assert_equal @var1.evidence_name, @var1.name
|
97
|
+
end
|
98
|
+
|
99
|
+
def test_generate_probability_table
|
100
|
+
test_probability_table
|
101
|
+
end
|
102
|
+
|
103
|
+
def test_get_observed_state
|
104
|
+
evidence = {:var1 => :true}
|
105
|
+
assert_equal evidence[@var1.name], @var1.get_observed_state(evidence)
|
106
|
+
end
|
107
|
+
|
108
|
+
def test_get_random_state
|
109
|
+
states = [:good, :bad, :ugly]
|
110
|
+
n = Sbn::Variable.new(@net, :george, [0.25, 0.25, 0.5], states)
|
111
|
+
evidence = {}
|
112
|
+
assert states.include?(n.get_random_state(evidence))
|
113
|
+
assert states.include?(n.get_random_state_with_markov_blanket(evidence))
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_parents
|
117
|
+
assert @var1.parents.class == Array and @var1.parents.empty?
|
118
|
+
end
|
119
|
+
|
120
|
+
def test_probability_table
|
121
|
+
@var1.add_child(@var2)
|
122
|
+
|
123
|
+
# number of probabilities no longer matches number of states because
|
124
|
+
# var2 now has a parent.
|
125
|
+
assert_nil @var2.probability_table
|
126
|
+
|
127
|
+
@var2.set_probabilities([0.25, 0.75, 0.2, 0.8])
|
128
|
+
assert_not_nil @var2.probability_table
|
129
|
+
|
130
|
+
expected_table = [[[:true, :true], 0.25],
|
131
|
+
[[:true, :false], 0.75],
|
132
|
+
[[:false, :true], 0.2],
|
133
|
+
[[:false, :false], 0.8]]
|
134
|
+
assert_equal @var2.probability_table, expected_table
|
135
|
+
end
|
136
|
+
|
137
|
+
def test_set_in_evidence_eh
|
138
|
+
evidence = {:var1 => :true, :var2 => :false}
|
139
|
+
assert @var1.set_in_evidence?(evidence)
|
140
|
+
assert @var2.set_in_evidence?(evidence)
|
141
|
+
end
|
142
|
+
|
143
|
+
def test_set_probabilities
|
144
|
+
@var1.add_child(@var2)
|
145
|
+
probs = @var2.instance_variable_get('@probabilities')
|
146
|
+
new_probs = [0.25, 0.75, 0.2, 0.8]
|
147
|
+
assert_not_equal probs, new_probs
|
148
|
+
|
149
|
+
@var2.set_probabilities(new_probs)
|
150
|
+
probs = @var2.instance_variable_get('@probabilities')
|
151
|
+
assert_not_nil probs, new_probs
|
152
|
+
end
|
153
|
+
|
154
|
+
def test_set_probability
|
155
|
+
@var1.add_child(@var2)
|
156
|
+
@var2.set_probability(0.75, {:var1 => :false, :var2 => :false})
|
157
|
+
probs = @var2.instance_variable_get('@probabilities')
|
158
|
+
assert_equal probs[3], 0.75
|
159
|
+
end
|
160
|
+
|
161
|
+
def test_set_states
|
162
|
+
var = Sbn::Variable.new(@net, :var3, [], [])
|
163
|
+
assert var.states.empty?
|
164
|
+
var.set_states([:true, :false])
|
165
|
+
assert !var.states.empty?
|
166
|
+
assert_equal var.states, [:true, :false]
|
167
|
+
end
|
168
|
+
|
169
|
+
def test_states
|
170
|
+
var = Sbn::Variable.new(@net, :var3, [], [])
|
171
|
+
assert_not_nil var.states
|
172
|
+
assert_equal var.states, []
|
173
|
+
end
|
174
|
+
|
175
|
+
def test_to_xmlbif_definition
|
176
|
+
xml = Builder::XmlMarkup.new(:indent => 2)
|
177
|
+
expected_output = <<-EOS
|
178
|
+
<definition>
|
179
|
+
<for>var1</for>
|
180
|
+
<table>0.5 0.5</table>
|
181
|
+
</definition>
|
182
|
+
EOS
|
183
|
+
assert_equal @var1.to_xmlbif_definition(xml).gsub(/\s+/, ''), expected_output.gsub(/\s+/, '')
|
184
|
+
end
|
185
|
+
|
186
|
+
def test_to_xmlbif_variable
|
187
|
+
xml = Builder::XmlMarkup.new(:indent => 2)
|
188
|
+
expected_output = <<-EOS
|
189
|
+
<variable type="nature">
|
190
|
+
<name>var1</name>
|
191
|
+
<outcome>true</outcome>
|
192
|
+
<outcome>false</outcome>
|
193
|
+
<property>SbnVariableType = Sbn::Variable</property>
|
194
|
+
</variable>
|
195
|
+
EOS
|
196
|
+
assert_equal @var1.to_xmlbif_variable(xml).gsub(/\s+/, ''), expected_output.gsub(/\s+/, '')
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
class TestNumericVariable < Test::Unit::TestCase # :nodoc:
|
201
|
+
def setup
|
202
|
+
@net = Sbn::Net.new
|
203
|
+
@var1 = Sbn::NumericVariable.new(@net, "var1", [0.25, 0.25, 0.25, 0.25], [5.0, 10.0, 15.0])
|
204
|
+
end
|
205
|
+
|
206
|
+
def test_get_observed_state
|
207
|
+
evidence = {:var1 => 7.68}
|
208
|
+
states = @var1.states
|
209
|
+
assert_equal @var1.get_observed_state(evidence), states[1]
|
210
|
+
end
|
211
|
+
|
212
|
+
def test_set_probabilities_from_sample_points
|
213
|
+
data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0]
|
214
|
+
temp_data = data.dup
|
215
|
+
@var1.add_sample_point({:var1 => temp_data.shift})
|
216
|
+
@var1.add_sample_point({:var1 => temp_data.shift})
|
217
|
+
@var1.add_sample_point({:var1 => temp_data.shift})
|
218
|
+
@var1.add_sample_point({:var1 => temp_data.shift})
|
219
|
+
@var1.add_sample_point({:var1 => temp_data.shift})
|
220
|
+
@var1.add_sample_point({:var1 => temp_data.shift})
|
221
|
+
@var1.add_sample_point({:var1 => temp_data.shift})
|
222
|
+
@var1.add_sample_point({:var1 => temp_data.shift})
|
223
|
+
@var1.add_sample_point({:var1 => temp_data.shift})
|
224
|
+
@var1.add_sample_point({:var1 => temp_data.shift})
|
225
|
+
@var1.add_sample_point({:var1 => temp_data.shift})
|
226
|
+
@var1.set_probabilities_from_sample_points!
|
227
|
+
assert_equal @var1.state_thresholds.shift, data.average - (data.standard_deviation * 2.0)
|
228
|
+
end
|
229
|
+
|
230
|
+
def test_state_thresholds
|
231
|
+
assert_equal @var1.state_thresholds, [5.0, 10.0, 15.0]
|
232
|
+
end
|
233
|
+
|
234
|
+
def test_to_xmlbif_variable
|
235
|
+
xml = Builder::XmlMarkup.new(:indent => 2)
|
236
|
+
expected_output = <<-EOS
|
237
|
+
<variable type="nature">
|
238
|
+
<name>var1</name>
|
239
|
+
<outcome>lt5.0</outcome>
|
240
|
+
<outcome>gte5.0lt10.0</outcome>
|
241
|
+
<outcome>gte10.0lt15.0</outcome>
|
242
|
+
<outcome>gte15.0</outcome>
|
243
|
+
<property>SbnVariableType = Sbn::NumericVariable</property>
|
244
|
+
<property>StateThresholds = 5.0,10.0,15.0</property>
|
245
|
+
</variable>
|
246
|
+
EOS
|
247
|
+
assert_equal @var1.to_xmlbif_variable(xml).gsub(/\s+/, ''), expected_output.gsub(/\s+/, '')
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
class TestStringVariable < Test::Unit::TestCase # :nodoc:
|
252
|
+
def setup
|
253
|
+
@net = Sbn::Net.new("Categorization")
|
254
|
+
@category = Sbn::Variable.new(@net, :category, [0.33, 0.33, 0.33], [:food, :groceries, :gas])
|
255
|
+
@text = Sbn::StringVariable.new(@net, :text)
|
256
|
+
@category.add_child(@text)
|
257
|
+
@net.learn([
|
258
|
+
{:category => :food, :text => 'foo'},
|
259
|
+
{:category => :food, :text => 'gro'},
|
260
|
+
{:category => :food, :text => 'foo'},
|
261
|
+
{:category => :food, :text => 'foo'},
|
262
|
+
{:category => :groceries, :text => 'gro'},
|
263
|
+
{:category => :groceries, :text => 'gro'},
|
264
|
+
{:category => :groceries, :text => 'foo'},
|
265
|
+
{:category => :groceries, :text => 'gro'},
|
266
|
+
{:category => :gas, :text => 'gas'},
|
267
|
+
{:category => :gas, :text => 'gas'},
|
268
|
+
{:category => :gas, :text => 'gas'},
|
269
|
+
{:category => :gas, :text => 'gas'}
|
270
|
+
])
|
271
|
+
@covars = @text.covariables
|
272
|
+
end
|
273
|
+
|
274
|
+
def test_covar_evidence_name
|
275
|
+
@covars.each do |covar|
|
276
|
+
manager_name = covar.instance_variable_get('@manager_name')
|
277
|
+
assert_equal @text.name, manager_name
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
def test_covar_get_observed_state
|
282
|
+
evidence = {:text => "groceries"}
|
283
|
+
@covars.each do |covar|
|
284
|
+
manager_name = covar.instance_variable_get('@manager_name')
|
285
|
+
text_to_match = covar.instance_variable_get('@text_to_match')
|
286
|
+
assert_equal covar.get_observed_state(evidence), (evidence[manager_name].include?(text_to_match) ? :true : :false)
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
def test_covar_to_xmlbif_variable
|
291
|
+
xml = Builder::XmlMarkup.new(:indent => 2)
|
292
|
+
expected_output = <<-EOS
|
293
|
+
<variable type="nature">
|
294
|
+
<name>text_covar_foo</name>
|
295
|
+
<outcome>true</outcome>
|
296
|
+
<outcome>false</outcome>
|
297
|
+
<property>SbnVariableType = Sbn::StringCovariable</property>
|
298
|
+
<property>ManagerVariableName = text</property>
|
299
|
+
<property>TextToMatch = "foo"</property>
|
300
|
+
</variable>
|
301
|
+
EOS
|
302
|
+
assert @covars.first.to_xmlbif_variable(xml).gsub(/\s+/, ''), expected_output.gsub(/\s+/, '')
|
303
|
+
end
|
304
|
+
|
305
|
+
def test_add_child_no_recurse
|
306
|
+
covariable_children = @text.instance_variable_get('@covariable_children')
|
307
|
+
newvar = Sbn::Variable.new(@net, :newvar)
|
308
|
+
assert !covariable_children.include?(newvar)
|
309
|
+
@text.add_child(newvar)
|
310
|
+
covariable_children = @text.instance_variable_get('@covariable_children')
|
311
|
+
assert covariable_children.include?(newvar)
|
312
|
+
end
|
313
|
+
|
314
|
+
def test_add_covariable
|
315
|
+
covar = Sbn::StringCovariable.new(@net, :text, 'something', [0.5, 0.5])
|
316
|
+
assert !@text.covariables.include?(covar)
|
317
|
+
@text.add_covariable(covar)
|
318
|
+
assert @text.covariables.include?(covar)
|
319
|
+
end
|
320
|
+
|
321
|
+
def test_add_parent_no_recurse
|
322
|
+
covariable_parents = @text.instance_variable_get('@covariable_parents')
|
323
|
+
newvar = Sbn::Variable.new(@net, :newvar)
|
324
|
+
assert !covariable_parents.include?(newvar)
|
325
|
+
@text.add_parent(newvar)
|
326
|
+
covariable_parents = @text.instance_variable_get('@covariable_parents')
|
327
|
+
assert covariable_parents.include?(newvar)
|
328
|
+
end
|
329
|
+
|
330
|
+
def test_add_sample_point
|
331
|
+
# make sure covariables are created with each sample point
|
332
|
+
newtext = "newtext"
|
333
|
+
assert_equal 3, @text.covariables.size
|
334
|
+
@text.add_sample_point({:text => newtext, :category => :gas})
|
335
|
+
ngrams = []
|
336
|
+
Sbn::StringVariable::DEFAULT_NGRAM_SIZES.each {|len| ngrams.concat(newtext.ngrams(len)) }
|
337
|
+
assert_equal 3 + ngrams.size, @text.covariables.size
|
338
|
+
end
|
339
|
+
|
340
|
+
def test_covariables
|
341
|
+
assert_not_nil @text.covariables
|
342
|
+
end
|
343
|
+
|
344
|
+
def test_set_in_evidence_eh
|
345
|
+
# assert_raise(RuntimeError) { @text.set_in_evidence?({:text => "newtext", :category => :gas}) }
|
346
|
+
assert @text.set_in_evidence?({:text => "newtext", :category => :gas})
|
347
|
+
end
|
348
|
+
|
349
|
+
def test_to_xmlbif_definition
|
350
|
+
xml = Builder::XmlMarkup.new(:indent => 2)
|
351
|
+
assert_nil @text.to_xmlbif_definition(xml)
|
352
|
+
end
|
353
|
+
|
354
|
+
def test_to_xmlbif_variable
|
355
|
+
xml = Builder::XmlMarkup.new(:indent => 2)
|
356
|
+
expected_output = <<-EOS
|
357
|
+
<variable type="nature">
|
358
|
+
<name>text</name>
|
359
|
+
<property>SbnVariableType = Sbn::StringVariable</property>
|
360
|
+
<property>Covariables = foo,gas,gro</property>
|
361
|
+
<property>Parents = category</property>
|
362
|
+
</variable>
|
363
|
+
EOS
|
364
|
+
assert_equal expected_output.gsub(/\s+/, ''), @text.to_xmlbif_variable(xml).gsub(/\s+/, '')
|
365
|
+
end
|
366
|
+
|
367
|
+
def test_is_complete_evidence_eh
|
368
|
+
evidence = {}
|
369
|
+
assert !@text.is_complete_evidence?(evidence)
|
370
|
+
evidence = {:category => :food, :text => "foo"}
|
371
|
+
assert @text.is_complete_evidence?(evidence)
|
372
|
+
end
|
373
|
+
end
|
metadata
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.9.2
|
3
|
+
specification_version: 1
|
4
|
+
name: sbn
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 0.9.0
|
7
|
+
date: 2007-03-15 00:00:00 -06:00
|
8
|
+
summary: Simple Bayesian Network Library
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: carl@youngbloods.org
|
12
|
+
homepage: http://youngbloods.org/
|
13
|
+
rubyforge_project:
|
14
|
+
description:
|
15
|
+
autorequire: sbn
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
post_install_message:
|
29
|
+
authors:
|
30
|
+
- Carl Youngblood
|
31
|
+
files:
|
32
|
+
- test/sbn.rb
|
33
|
+
- test/test_combination.rb
|
34
|
+
- test/test_helpers.rb
|
35
|
+
- test/test_learning.rb
|
36
|
+
- test/test_net.rb
|
37
|
+
- test/test_variable.rb
|
38
|
+
- lib/combination.rb
|
39
|
+
- lib/formats.rb
|
40
|
+
- lib/helpers.rb
|
41
|
+
- lib/inference.rb
|
42
|
+
- lib/learning.rb
|
43
|
+
- lib/net.rb
|
44
|
+
- lib/numeric_variable.rb
|
45
|
+
- lib/sbn.rb
|
46
|
+
- lib/string_variable.rb
|
47
|
+
- lib/variable.rb
|
48
|
+
- README
|
49
|
+
test_files:
|
50
|
+
- test/sbn.rb
|
51
|
+
rdoc_options:
|
52
|
+
- --main
|
53
|
+
- README
|
54
|
+
extra_rdoc_files:
|
55
|
+
- README
|
56
|
+
executables: []
|
57
|
+
|
58
|
+
extensions: []
|
59
|
+
|
60
|
+
requirements: []
|
61
|
+
|
62
|
+
dependencies: []
|
63
|
+
|