fathom 0.3.7 → 0.5.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/.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
|