fathom 0.3.7 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.autotest +7 -5
- data/.document +2 -2
- data/Gemfile +9 -10
- data/{LICENSE → LICENSE.txt} +1 -1
- data/README.md +29 -90
- data/Rakefile +34 -32
- data/VERSION +1 -1
- data/fathom.gemspec +105 -0
- data/features/fathom.feature +26 -0
- data/features/step_definitions/fathom_steps.rb +23 -0
- data/features/support/env.rb +13 -0
- data/lib/ext/array.rb +6 -2
- data/lib/ext/string.rb +86 -7
- data/lib/fathom.rb +51 -88
- data/lib/fathom/behaviors/attribute_system.rb +91 -0
- data/lib/fathom/behaviors/context_behavior.rb +28 -0
- data/lib/fathom/behaviors/plugins.rb +16 -0
- data/lib/fathom/contexts/network_population.rb +47 -0
- data/lib/fathom/contexts/network_traversal.rb +4 -0
- data/lib/fathom/data/adjacency_matrix.rb +27 -0
- data/lib/fathom/data/definition.rb +22 -0
- data/lib/fathom/data/edge.rb +58 -0
- data/lib/fathom/data/network.rb +35 -0
- data/lib/fathom/data/outcome.rb +30 -0
- data/lib/fathom/data/property.rb +31 -0
- data/lib/fathom/data/variable.rb +59 -0
- data/lib/fathom/roles/general_graph_tools.rb +87 -0
- data/lib/fathom/roles/network_builder.rb +61 -0
- data/spec/fathom/behaviors/attribute_system_spec.rb +141 -0
- data/spec/fathom/behaviors/context_behavior_spec.rb +15 -0
- data/spec/fathom/behaviors/plugins_spec.rb +80 -0
- data/spec/fathom/contexts/network_population_spec.rb +55 -0
- data/spec/fathom/contexts/network_traversal_spec.rb +11 -0
- data/spec/fathom/data/adjacency_matrix_spec.rb +42 -0
- data/spec/fathom/data/definition_spec.rb +19 -0
- data/spec/fathom/data/edge_spec.rb +77 -0
- data/spec/fathom/data/network_spec.rb +72 -0
- data/spec/fathom/data/outcome_spec.rb +17 -0
- data/spec/fathom/data/property_spec.rb +17 -0
- data/spec/fathom/data/variable_spec.rb +101 -0
- data/spec/fathom/ext/array_spec.rb +17 -0
- data/spec/fathom/ext/string_spec.rb +90 -0
- data/spec/fathom/roles/general_graph_tools_spec.rb +95 -0
- data/spec/fathom/roles/network_builder_spec.rb +90 -0
- data/spec/fathom_spec.rb +28 -49
- data/spec/spec_helper.rb +7 -11
- data/spec/support/context_behavior.rb +14 -0
- data/spec/support/custom_matchers.rb +12 -0
- data/spec/support/files.rb +8 -0
- data/spec/support/network.yml +42 -0
- metadata +133 -174
- data/.bundle/config +0 -2
- data/.gitignore +0 -6
- data/Gemfile.lock +0 -42
- data/TODO.md +0 -127
- data/autotest/discover.rb +0 -1
- data/lib/ext/faster_csv.rb +0 -1
- data/lib/ext/open_struct.rb +0 -17
- data/lib/fathom/agent.rb +0 -48
- data/lib/fathom/agent/agent_cluster.rb +0 -23
- data/lib/fathom/agent/properties.rb +0 -48
- data/lib/fathom/archive/causal_graph.rb +0 -12
- data/lib/fathom/archive/concept.rb +0 -83
- data/lib/fathom/archive/conditional_probability_matrix.rb +0 -119
- data/lib/fathom/archive/inverter.rb +0 -20
- data/lib/fathom/archive/n2.rb +0 -198
- data/lib/fathom/archive/n3.rb +0 -119
- data/lib/fathom/archive/node.rb +0 -97
- data/lib/fathom/archive/noodle.rb +0 -136
- data/lib/fathom/archive/scratch.rb +0 -45
- data/lib/fathom/distributions.rb +0 -8
- data/lib/fathom/distributions/discrete_gaussian.rb +0 -44
- data/lib/fathom/distributions/discrete_uniform.rb +0 -25
- data/lib/fathom/distributions/gaussian.rb +0 -46
- data/lib/fathom/distributions/uniform.rb +0 -35
- data/lib/fathom/import.rb +0 -85
- data/lib/fathom/import/csv_import.rb +0 -59
- data/lib/fathom/import/import_node.rb +0 -17
- data/lib/fathom/import/yaml_import.rb +0 -74
- data/lib/fathom/knowledge_base.rb +0 -46
- data/lib/fathom/knowledge_base/search.rb +0 -19
- data/lib/fathom/monte_carlo_set.rb +0 -152
- data/lib/fathom/node.rb +0 -139
- data/lib/fathom/node/belief_node.rb +0 -121
- data/lib/fathom/node/cpm_node.rb +0 -100
- data/lib/fathom/node/data_collection.rb +0 -97
- data/lib/fathom/node/data_node.rb +0 -22
- data/lib/fathom/node/decision.rb +0 -11
- data/lib/fathom/node/discrete_node.rb +0 -41
- data/lib/fathom/node/fact.rb +0 -24
- data/lib/fathom/node/mc_node.rb +0 -70
- data/lib/fathom/node/node_extensions/enforced_name.rb +0 -12
- data/lib/fathom/node/node_extensions/numeric_methods.rb +0 -68
- data/lib/fathom/node/plausible_range.rb +0 -98
- data/lib/fathom/simulation.rb +0 -59
- data/lib/fathom/simulation/tick_methods.rb +0 -25
- data/lib/fathom/simulation/tick_simulation.rb +0 -12
- data/lib/fathom/value_description.rb +0 -79
- data/lib/options_hash.rb +0 -186
- data/spec/ext/array_spec.rb +0 -10
- data/spec/ext/faster_csv_spec.rb +0 -10
- data/spec/ext/open_struct_spec.rb +0 -20
- data/spec/ext/string_spec.rb +0 -7
- data/spec/fathom/agent/agent_cluster_spec.rb +0 -17
- data/spec/fathom/agent_spec.rb +0 -51
- data/spec/fathom/distributions/discrete_gaussian_spec.rb +0 -64
- data/spec/fathom/distributions/discrete_uniform_spec.rb +0 -0
- data/spec/fathom/distributions/gaussian_spec.rb +0 -64
- data/spec/fathom/distributions/uniform_spec.rb +0 -0
- data/spec/fathom/import/csv_import_spec.rb +0 -52
- data/spec/fathom/import/import_node_spec.rb +0 -10
- data/spec/fathom/import/yaml_import_spec.rb +0 -73
- data/spec/fathom/import_spec.rb +0 -36
- data/spec/fathom/knowledge_base_spec.rb +0 -20
- data/spec/fathom/monte_carlo_set_spec.rb +0 -149
- data/spec/fathom/node/belief_node_spec.rb +0 -180
- data/spec/fathom/node/cpm_node_spec.rb +0 -144
- data/spec/fathom/node/data_collection_spec.rb +0 -26
- data/spec/fathom/node/data_node_spec.rb +0 -102
- data/spec/fathom/node/decision_spec.rb +0 -15
- data/spec/fathom/node/discrete_node_spec.rb +0 -56
- data/spec/fathom/node/fact_spec.rb +0 -33
- data/spec/fathom/node/mc_node_spec.rb +0 -66
- data/spec/fathom/node/node_extensions/enforced_name_spec.rb +0 -15
- data/spec/fathom/node/node_extensions/numeric_methods_spec.rb +0 -124
- data/spec/fathom/node/plausible_range_spec.rb +0 -151
- data/spec/fathom/node_spec.rb +0 -172
- data/spec/fathom/simulation/tick_simulation_spec.rb +0 -32
- data/spec/fathom/simulation_spec.rb +0 -24
- data/spec/fathom/value_description_spec.rb +0 -70
- data/spec/support/demo.yml +0 -17
- data/spec/support/demo_agent.rb +0 -8
- data/spec/support/dummy_numeric_node.rb +0 -8
- data/spec/support/fact.yml +0 -11
@@ -1,144 +0,0 @@
|
|
1
|
-
require File.expand_path('../../../spec_helper', __FILE__)
|
2
|
-
|
3
|
-
describe CPMNode do
|
4
|
-
|
5
|
-
before do
|
6
|
-
@child = BeliefNode.new(:name => :color, :values => {:red => 0.4, :green => 0.6})
|
7
|
-
@parent = BeliefNode.new(:name => :child, :values => {:asher => 0.2, :stella => 0.8})
|
8
|
-
@cpm = CPMNode.new(:child => @child, :parent => @parent)
|
9
|
-
end
|
10
|
-
|
11
|
-
it "should subclass Node" do
|
12
|
-
CPMNode.ancestors[1].should eql(Node)
|
13
|
-
end
|
14
|
-
|
15
|
-
it "should allow a BeliefNode child and parent" do
|
16
|
-
@cpm.parent.should eql(@parent)
|
17
|
-
@cpm.child.should eql(@child)
|
18
|
-
end
|
19
|
-
|
20
|
-
it "should generate a conditional probability matrix from the parent and child" do
|
21
|
-
parent_values = @cpm.parent.probabilities.col
|
22
|
-
child_values = @cpm.child.probabilities
|
23
|
-
matrix = parent_values * child_values
|
24
|
-
@cpm.values.to_a.should eql(matrix.to_a)
|
25
|
-
end
|
26
|
-
|
27
|
-
it "should alias the values with matrix" do
|
28
|
-
@cpm.values.should eql(@cpm.matrix)
|
29
|
-
end
|
30
|
-
|
31
|
-
it "should raise an error when trying to load non-BeliefNode parent or child" do
|
32
|
-
lambda{CPMNode.new(:child => :not_a_belief_node, :parent => @parent)}.should raise_error(/must be a BeliefNode/)
|
33
|
-
lambda{CPMNode.new(:child => @child, :parent => :not_a_belief_node)}.should raise_error(/must be a BeliefNode/)
|
34
|
-
end
|
35
|
-
|
36
|
-
it "should have a probability lookup" do
|
37
|
-
@cpm.should be_respond_to(:probability)
|
38
|
-
end
|
39
|
-
|
40
|
-
it "should only allow options for the parent and child names" do
|
41
|
-
lambda{@cpm.probability :not_a_link => true}.should raise_error(/unknown/i)
|
42
|
-
end
|
43
|
-
|
44
|
-
it "should be able to lookup the values we're looking for" do
|
45
|
-
# The Matrix looks like this:
|
46
|
-
# GSL::Matrix
|
47
|
-
# [ 8.000e-02 1.200e-01
|
48
|
-
# 3.200e-01 4.800e-01 ]
|
49
|
-
@cpm.probability(:color => :red, :child => :asher).should be_within(1e-10).of(0.08)
|
50
|
-
@cpm.probability(:color => :red, :child => :stella).should be_within(1e-10).of(0.32)
|
51
|
-
@cpm.probability(:color => :green, :child => :asher).should be_within(1e-10).of(0.12)
|
52
|
-
@cpm.probability(:color => :green, :child => :stella).should be_within(1e-10).of(0.48)
|
53
|
-
end
|
54
|
-
|
55
|
-
it "should look for all children values, if no child is provided" do
|
56
|
-
@cpm.probability(:child => :asher).should be_within(1e-10).of(0.2)
|
57
|
-
@cpm.probability(:child => :stella).should be_within(1e-10).of(0.8)
|
58
|
-
end
|
59
|
-
|
60
|
-
it "should look for all parent values, if no parent is provided" do
|
61
|
-
@cpm.probability(:color => :red).should be_within(1e-10).of(0.4)
|
62
|
-
@cpm.probability(:color => :green).should be_within(1e-10).of(0.6)
|
63
|
-
end
|
64
|
-
|
65
|
-
it "should provide a probability of 1 if no filter is set" do
|
66
|
-
@cpm.probability.should be_within(1e-10).of(1.0)
|
67
|
-
end
|
68
|
-
|
69
|
-
it "should give a description in a hash, if description is turned on" do
|
70
|
-
@cpm.probability(:color => :red, :child => :asher, :describe => true).keys.first.should eql('P(red | asher)')
|
71
|
-
@cpm.probability(:color => :red, :child => :stella, :describe => true).keys.first.should eql('P(red | stella)')
|
72
|
-
@cpm.probability(:color => :green, :child => :asher, :describe => true).keys.first.should eql('P(green | asher)')
|
73
|
-
@cpm.probability(:color => :green, :child => :stella, :describe => true).keys.first.should eql('P(green | stella)')
|
74
|
-
@cpm.probability(:child => :asher, :describe => true).keys.first.should eql('P(red or green | asher)')
|
75
|
-
@cpm.probability(:child => :stella, :describe => true).keys.first.should eql('P(red or green | stella)')
|
76
|
-
@cpm.probability(:color => :red, :describe => true).keys.first.should eql('P(red | asher or stella)')
|
77
|
-
@cpm.probability(:color => :green, :describe => true).keys.first.should eql('P(green | asher or stella)')
|
78
|
-
@cpm.probability(:describe => true).keys.first.should eql('P(red or green | asher or stella)')
|
79
|
-
end
|
80
|
-
|
81
|
-
it "should alias p for probability" do
|
82
|
-
@cpm.p(:color => :red, :child => :asher).should be_within(1e-10).of(0.08)
|
83
|
-
@cpm.p(:color => :red, :child => :stella).should be_within(1e-10).of(0.32)
|
84
|
-
@cpm.p(:color => :green, :child => :asher).should be_within(1e-10).of(0.12)
|
85
|
-
@cpm.p(:color => :green, :child => :stella).should be_within(1e-10).of(0.48)
|
86
|
-
@cpm.p(:child => :asher).should be_within(1e-10).of(0.2)
|
87
|
-
@cpm.p(:child => :stella).should be_within(1e-10).of(0.8)
|
88
|
-
@cpm.p(:color => :red).should be_within(1e-10).of(0.4)
|
89
|
-
@cpm.p(:color => :green).should be_within(1e-10).of(0.6)
|
90
|
-
@cpm.p.should be_within(1e-10).of(1.0)
|
91
|
-
end
|
92
|
-
|
93
|
-
it "should have odds for any query" do
|
94
|
-
@cpm.odds(:color => :red, :child => :asher).should be_within(1e-3).of(0.087)
|
95
|
-
@cpm.odds(:color => :red, :child => :stella).should be_within(1e-3).of(0.471)
|
96
|
-
@cpm.odds(:color => :green, :child => :asher).should be_within(1e-3).of(0.136)
|
97
|
-
@cpm.odds(:color => :green, :child => :stella).should be_within(1e-3).of(0.923)
|
98
|
-
@cpm.odds(:child => :asher).should be_within(1e-3).of(0.25)
|
99
|
-
@cpm.odds(:child => :stella).should be_within(1e-3).of(4.0)
|
100
|
-
@cpm.odds(:color => :red).should be_within(1e-3).of(0.666)
|
101
|
-
@cpm.odds(:color => :green).should be_within(1e-3).of(1.5)
|
102
|
-
@cpm.odds.should eql(1 / 0.0)
|
103
|
-
end
|
104
|
-
|
105
|
-
it "should alias o for odds" do
|
106
|
-
@cpm.o(:color => :red, :child => :asher).should be_within(1e-3).of(0.087)
|
107
|
-
@cpm.o(:color => :red, :child => :stella).should be_within(1e-3).of(0.471)
|
108
|
-
@cpm.o(:color => :green, :child => :asher).should be_within(1e-3).of(0.136)
|
109
|
-
@cpm.o(:color => :green, :child => :stella).should be_within(1e-3).of(0.923)
|
110
|
-
@cpm.o(:child => :asher).should be_within(1e-3).of(0.25)
|
111
|
-
@cpm.o(:child => :stella).should be_within(1e-3).of(4.0)
|
112
|
-
@cpm.o(:color => :red).should be_within(1e-3).of(0.666)
|
113
|
-
@cpm.o(:color => :green).should be_within(1e-3).of(1.5)
|
114
|
-
@cpm.o.should eql(1 / 0.0)
|
115
|
-
end
|
116
|
-
|
117
|
-
it "should default the name to :cpm" do
|
118
|
-
@cpm.name.should eql(:cpm)
|
119
|
-
end
|
120
|
-
|
121
|
-
it "should default the description" do
|
122
|
-
@cpm.description.should eql("Conditional Probability Matrix from child to color.")
|
123
|
-
end
|
124
|
-
|
125
|
-
it "should return a vector for likelihood" do
|
126
|
-
@cpm.likelihood(:red).should be_a(GSL::Vector)
|
127
|
-
end
|
128
|
-
|
129
|
-
it "should offer the likelihood of each parent value, given a child value" do
|
130
|
-
values = @cpm.likelihood(:red).to_a
|
131
|
-
values.sort.map {|e| (e * 100).to_i}.should eql([8, 32])
|
132
|
-
|
133
|
-
values = @cpm.likelihood(:green).to_a
|
134
|
-
values.sort.map {|e| (e * 100).to_i}.should eql([12, 48])
|
135
|
-
end
|
136
|
-
|
137
|
-
it "should offer l as an alias for likelihood" do
|
138
|
-
values = @cpm.l(:red).to_a
|
139
|
-
values.sort.map {|e| (e * 100).to_i}.should eql([8, 32])
|
140
|
-
|
141
|
-
values = @cpm.l(:green).to_a
|
142
|
-
values.sort.map {|e| (e * 100).to_i}.should eql([12, 48])
|
143
|
-
end
|
144
|
-
end
|
@@ -1,26 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
-
|
3
|
-
include Fathom
|
4
|
-
|
5
|
-
describe DataCollection do
|
6
|
-
it "should be a node" do
|
7
|
-
DataCollection.ancestors.should be_include(Node)
|
8
|
-
end
|
9
|
-
|
10
|
-
it "should be a DiscreteNode as well" do
|
11
|
-
DataCollection.ancestors.should be_include(DiscreteNode)
|
12
|
-
end
|
13
|
-
|
14
|
-
it "should be able to extract the discrete labels from the first discrete parent node added to it" do
|
15
|
-
pr = PlausibleRange.new(:min => 0, :max => 1)
|
16
|
-
dn = DiscreteNode.new(:labels => [1,2,3])
|
17
|
-
dc = DataCollection.new(:parents => [pr, dn])
|
18
|
-
dc.labels.should eql([1,2,3])
|
19
|
-
end
|
20
|
-
|
21
|
-
it "should enforce a name" do
|
22
|
-
dc = DataCollection.new(:labels => [1,2,3])
|
23
|
-
dc.name.should_not be_nil
|
24
|
-
end
|
25
|
-
|
26
|
-
end
|
@@ -1,102 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
-
|
3
|
-
include Fathom
|
4
|
-
|
5
|
-
describe DataNode do
|
6
|
-
|
7
|
-
before do
|
8
|
-
@values = [1,2,3,4,5]
|
9
|
-
@opts = {:values => @values}
|
10
|
-
@dn = DataNode.new(@opts)
|
11
|
-
@vector = GSL::Vector.ary_to_gv(@values)
|
12
|
-
end
|
13
|
-
|
14
|
-
it "should initialize requiring values in the options" do
|
15
|
-
lambda{DataNode.new}.should raise_error(/values/)
|
16
|
-
lambda{DataNode.new(:values => @values)}.should_not raise_error
|
17
|
-
end
|
18
|
-
|
19
|
-
it "should make the values readable" do
|
20
|
-
@dn.values.should eql(@values)
|
21
|
-
end
|
22
|
-
|
23
|
-
it "should allow an optional name for the node" do
|
24
|
-
@dn = DataNode.new(:values => @values, :name => "Demo Name")
|
25
|
-
@dn.name.should eql("Demo Name")
|
26
|
-
end
|
27
|
-
|
28
|
-
it "should take an optional distribiution" do
|
29
|
-
@dn = DataNode.new(@opts.merge(:distribution => :gaussian))
|
30
|
-
@dn.distribution.should eql(Fathom::Distributions::Gaussian)
|
31
|
-
end
|
32
|
-
|
33
|
-
it "should create a vector from the values" do
|
34
|
-
@dn.vector.should ==(@vector)
|
35
|
-
end
|
36
|
-
|
37
|
-
it "should provide the standard deviation" do
|
38
|
-
@dn.standard_deviation.should ==(@vector.sd)
|
39
|
-
end
|
40
|
-
|
41
|
-
it "should alias sd and std for standard_deviation" do
|
42
|
-
@dn.sd.should eql(@dn.standard_deviation)
|
43
|
-
@dn.std.should eql(@dn.standard_deviation)
|
44
|
-
end
|
45
|
-
|
46
|
-
it "should be able to produce the mean" do
|
47
|
-
@dn.mean.should eql(@vector.mean)
|
48
|
-
end
|
49
|
-
|
50
|
-
it "should generate a random variable that fits the data's distribution" do
|
51
|
-
@dn.rand.should be_a(Float)
|
52
|
-
end
|
53
|
-
|
54
|
-
it "should have a name_sym method" do
|
55
|
-
dn = DataNode.new(:name => "Demo Node", :values => [1,2,3])
|
56
|
-
dn.name_sym.should eql(:demo_node)
|
57
|
-
end
|
58
|
-
|
59
|
-
it "should offer the lower bounds at a default confidence level of 0.05" do
|
60
|
-
GSL::Cdf.should_receive(:gaussian_Pinv).with(0.05, @dn.vector.sd).and_return(0.0)
|
61
|
-
@dn.inverse_cdf
|
62
|
-
end
|
63
|
-
|
64
|
-
it "should offer the lower bounds at an arbitrary confidence level" do
|
65
|
-
GSL::Cdf.should_receive(:gaussian_Pinv).with(0.95, @dn.vector.sd).and_return(0.0)
|
66
|
-
@dn.inverse_cdf(:confidence_interval => 0.95)
|
67
|
-
end
|
68
|
-
|
69
|
-
it "should be able to calculate the upper bound by passing upper as a parameter" do
|
70
|
-
GSL::Cdf.should_receive(:gaussian_Qinv).with(0.05, @dn.vector.sd).and_return(0.0)
|
71
|
-
@dn.inverse_cdf(:confidence_interval => 0.05, :upper => true)
|
72
|
-
end
|
73
|
-
|
74
|
-
it "should be able to calculate a lower_bound, an alias for inverse_cdf" do
|
75
|
-
GSL::Cdf.should_receive(:gaussian_Pinv).with(0.05, @dn.vector.sd).and_return(0.0)
|
76
|
-
@dn.lower_bound
|
77
|
-
end
|
78
|
-
|
79
|
-
it "should be able to pass arguments to lower_bound" do
|
80
|
-
GSL::Cdf.should_receive(:gaussian_Pinv).with(0.1, @dn.vector.sd).and_return(0.0)
|
81
|
-
@dn.lower_bound(:confidence_interval => 0.1)
|
82
|
-
end
|
83
|
-
|
84
|
-
it "should be able to calculate an upper_bound, a shortcut for inverse_cdf(confidence_interval, false)" do
|
85
|
-
GSL::Cdf.should_receive(:gaussian_Qinv).with(0.05, @dn.vector.sd).and_return(0.0)
|
86
|
-
@dn.upper_bound
|
87
|
-
end
|
88
|
-
|
89
|
-
it "should be able to pass arguments to upper_bound" do
|
90
|
-
GSL::Cdf.should_receive(:gaussian_Qinv).with(0.1, @dn.vector.sd).and_return(0.0)
|
91
|
-
@dn.upper_bound(:confidence_interval => 0.1)
|
92
|
-
end
|
93
|
-
|
94
|
-
it "should offset the cdf results by the mean" do
|
95
|
-
@dn.lower_bound.should eql(GSL::Cdf.gaussian_Pinv(0.05, @dn.vector.sd) + @dn.vector.mean)
|
96
|
-
end
|
97
|
-
|
98
|
-
it "should return the lower and upper bounds of a confidence interval" do
|
99
|
-
@dn.interval_values.should eql([@dn.lower_bound, @dn.upper_bound])
|
100
|
-
end
|
101
|
-
|
102
|
-
end
|
@@ -1,15 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
-
|
3
|
-
include Fathom
|
4
|
-
|
5
|
-
describe Decision do
|
6
|
-
it "should be a type of node" do
|
7
|
-
Decision.ancestors.should be_include(Node)
|
8
|
-
end
|
9
|
-
|
10
|
-
it "should not have a distribution or values" do
|
11
|
-
@d = Decision.new
|
12
|
-
@d.should_not be_respond_to(:distribution)
|
13
|
-
@d.should_not be_respond_to(:values)
|
14
|
-
end
|
15
|
-
end
|
@@ -1,56 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
-
|
3
|
-
include Fathom
|
4
|
-
|
5
|
-
describe DiscreteNode do
|
6
|
-
|
7
|
-
before do
|
8
|
-
@dn = DiscreteNode.new(:labels => [1,2,3])
|
9
|
-
end
|
10
|
-
|
11
|
-
it "should assign :true and :false for labels, if none are provided" do
|
12
|
-
lambda{@dn = DiscreteNode.new}.should_not raise_error
|
13
|
-
@dn.labels.should eql([:true, :false])
|
14
|
-
end
|
15
|
-
|
16
|
-
it "should create an array from a single value for its labels" do
|
17
|
-
dn = DiscreteNode.new(:labels => 1)
|
18
|
-
dn.labels.should eql([1])
|
19
|
-
end
|
20
|
-
|
21
|
-
it "should take the values and convert them to labels, if there are no labels provided" do
|
22
|
-
dn = DiscreteNode.new(:values => [1,2,3])
|
23
|
-
dn.labels.should eql([1,2,3])
|
24
|
-
end
|
25
|
-
|
26
|
-
it "should create a unique list of labels" do
|
27
|
-
dn = DiscreteNode.new(:labels => [1,1,2,3,1])
|
28
|
-
dn.labels.should eql([1,2,3])
|
29
|
-
end
|
30
|
-
|
31
|
-
it "should expose the size of the labels" do
|
32
|
-
@dn.size.should eql(3)
|
33
|
-
end
|
34
|
-
|
35
|
-
it "should alias length for size" do
|
36
|
-
@dn.length.should eql(3)
|
37
|
-
end
|
38
|
-
|
39
|
-
it "should have a default distribution of DiscreteUniform" do
|
40
|
-
@dn.distribution.should eql(Fathom::Distributions::DiscreteUniform)
|
41
|
-
end
|
42
|
-
|
43
|
-
it "should be able to produce a random variable from the discrete distribution" do
|
44
|
-
@dn = DiscreteNode.new(:labels => [1,2])
|
45
|
-
# 9.31322574615479e-10 chance of failing
|
46
|
-
30.times.map {@dn.rand}.uniq.sort.should eql([1,2])
|
47
|
-
end
|
48
|
-
|
49
|
-
it "should offer a uniform likelihood" do
|
50
|
-
@dn.likelihood(:anything).to_a.should eql([1.0, 1.0, 1.0])
|
51
|
-
end
|
52
|
-
|
53
|
-
it "should offer an alias of l for likelihood" do
|
54
|
-
@dn.l(:anything).to_a.should eql([1.0, 1.0, 1.0])
|
55
|
-
end
|
56
|
-
end
|
@@ -1,33 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
-
|
3
|
-
include Fathom
|
4
|
-
|
5
|
-
describe Fact do
|
6
|
-
before do
|
7
|
-
@f = Fact.new(
|
8
|
-
:value => 2,
|
9
|
-
:name => "Some Fact",
|
10
|
-
:description => "Just a demonstration of what a good fact may look like. Facts are really about things that are certain--there are 7 days in a week, that sort of thing. Too often I was creating a PlausibleRange with the min and max to the same value."
|
11
|
-
)
|
12
|
-
end
|
13
|
-
|
14
|
-
it "should be a Node" do
|
15
|
-
Fact.ancestors.should be_include(Fathom::Node)
|
16
|
-
end
|
17
|
-
|
18
|
-
it "should take a value (rather than values)" do
|
19
|
-
@f.value.should eql(2)
|
20
|
-
end
|
21
|
-
|
22
|
-
it "should return the value for rand" do
|
23
|
-
@f.rand.should eql(2)
|
24
|
-
end
|
25
|
-
|
26
|
-
it "should have removed the distribution and values methods" do
|
27
|
-
@f.should_not be_respond_to(:values)
|
28
|
-
@f.should_not be_respond_to(:distribution)
|
29
|
-
@n = Node.new(:distribution => :standard, :values => [1,2,3])
|
30
|
-
@n.values.should eql([1,2,3])
|
31
|
-
@n.distribution.should eql(Fathom::Distributions::Gaussian)
|
32
|
-
end
|
33
|
-
end
|
@@ -1,66 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
|
2
|
-
|
3
|
-
include Fathom
|
4
|
-
|
5
|
-
describe MCNode do
|
6
|
-
|
7
|
-
before(:all) do
|
8
|
-
@fields = [:value_result]
|
9
|
-
end
|
10
|
-
|
11
|
-
before do
|
12
|
-
@vd = lambda{|n| {:value_result => 1}}
|
13
|
-
@mcn = MCNode.new(:value_description => @vd)
|
14
|
-
end
|
15
|
-
|
16
|
-
it "should be a type of Node" do
|
17
|
-
MCNode.ancestors.should be_include(Fathom::Node)
|
18
|
-
end
|
19
|
-
|
20
|
-
it "should use a value_description from the command-line arguments" do
|
21
|
-
mcn = MCNode.new(:value_description => @vd)
|
22
|
-
mcn.value_description.should eql(@vd)
|
23
|
-
end
|
24
|
-
|
25
|
-
it "should be able to take a block instead of a named lambda for the value description" do
|
26
|
-
mcn = MCNode.new {|n| {:value_result => 1}}
|
27
|
-
mcn.value_description.should be_a(Proc)
|
28
|
-
end
|
29
|
-
|
30
|
-
it "should require a value_description from either a parameter or a block passed in" do
|
31
|
-
lambda{MCNode.new}.should raise_error(/value_description/)
|
32
|
-
end
|
33
|
-
|
34
|
-
it "should process with the default number of runs at 10,000", :slow => true do
|
35
|
-
lambda{@mcn.process}.should_not raise_error
|
36
|
-
@mcn.samples_taken.should eql(10_000)
|
37
|
-
end
|
38
|
-
|
39
|
-
it "should call the value_description block each time it is processed" do
|
40
|
-
@vd.should_receive(:call).exactly(3).times.with(@mcn).and_return({:value_result => 1})
|
41
|
-
@mcn.process(3)
|
42
|
-
end
|
43
|
-
|
44
|
-
it "should define children nodes for all keys in the result set" do
|
45
|
-
@mcn.process(1)
|
46
|
-
@mcn.value_result.should be_a(Node)
|
47
|
-
@mcn.value_result.values.should eql([1])
|
48
|
-
@mcn.value_result.vector.should be_a(GSL::Vector)
|
49
|
-
end
|
50
|
-
|
51
|
-
it "should be resetable" do
|
52
|
-
@mcn.process(1)
|
53
|
-
@mcn.reset!
|
54
|
-
lambda{@mcn.process(1)}.should_not raise_error
|
55
|
-
end
|
56
|
-
|
57
|
-
it "should expose the fields from the samples" do
|
58
|
-
@mcn.process(1)
|
59
|
-
sort_array_of_symbols(@mcn.fields).should eql(@fields)
|
60
|
-
end
|
61
|
-
|
62
|
-
|
63
|
-
end
|
64
|
-
def sort_array_of_symbols(array)
|
65
|
-
array.map {|e| e.to_s}.sort.map {|e| e.to_sym}
|
66
|
-
end
|