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
data/lib/fathom/archive/n3.rb
DELETED
@@ -1,119 +0,0 @@
|
|
1
|
-
class Array
|
2
|
-
def expand(array)
|
3
|
-
return array.map{|e| [e]} if self.empty?
|
4
|
-
array.inject([]) do |list, other_e|
|
5
|
-
self.each do |e|
|
6
|
-
list << [e,other_e].flatten
|
7
|
-
end
|
8
|
-
list
|
9
|
-
end
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
class Variable
|
14
|
-
|
15
|
-
attr_reader :values, :name, :observations, :total
|
16
|
-
|
17
|
-
def initialize(name, *values)
|
18
|
-
values = [true, false] if values.empty?
|
19
|
-
@name = name
|
20
|
-
@values = values
|
21
|
-
@observations = Array.new(@values.size, 0)
|
22
|
-
@total = 0
|
23
|
-
end
|
24
|
-
|
25
|
-
# You can observe anything but nothing: we record any observation but nil.
|
26
|
-
# If nil is set, we use the first value as the default.
|
27
|
-
def observe(value=nil)
|
28
|
-
value = self.values.first if value.nil?
|
29
|
-
unless self.values.include?(value)
|
30
|
-
self.values << value
|
31
|
-
self.observations << 0
|
32
|
-
end
|
33
|
-
index = self.values.index(value)
|
34
|
-
self.observations[index] += 1
|
35
|
-
@total += 1
|
36
|
-
end
|
37
|
-
|
38
|
-
# Lookup observations
|
39
|
-
def observed(value)
|
40
|
-
index = self.values.index(value)
|
41
|
-
return 0 unless index
|
42
|
-
self.observations[index]
|
43
|
-
end
|
44
|
-
|
45
|
-
def inspect
|
46
|
-
"Variable: #{self.name} #{self.values.inspect}"
|
47
|
-
end
|
48
|
-
|
49
|
-
class << self
|
50
|
-
def infer(obj, *values)
|
51
|
-
return obj if obj.is_a?(Variable)
|
52
|
-
case obj
|
53
|
-
when Symbol
|
54
|
-
Variable.new(obj, *values)
|
55
|
-
when String
|
56
|
-
Variable.new(obj.to_sym, *values)
|
57
|
-
else
|
58
|
-
nil
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
class Table
|
66
|
-
|
67
|
-
attr_reader :columns, :variables, :legend
|
68
|
-
def initialize(*variables)
|
69
|
-
@columns = variables.map {|v| v.name}
|
70
|
-
@variables = variables
|
71
|
-
@legend = @variables.inject([]) do |list, e|
|
72
|
-
list = list.expand(e)
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
protected
|
77
|
-
def lookup()
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
class Node
|
82
|
-
def initialize(name, *parents)
|
83
|
-
end
|
84
|
-
|
85
|
-
# Take an array, array of arrays, dictionary, hash, or OpenStruct.
|
86
|
-
# Anything but an array can add a new parent to observe.
|
87
|
-
def observe(values)
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
require 'rubygems'
|
92
|
-
require 'spec'
|
93
|
-
|
94
|
-
=begin
|
95
|
-
variables = [[:spring, :summer, :fall, :winter], [:true, :false], [:true, :false], [:true, :false]]
|
96
|
-
|
97
|
-
@all = []
|
98
|
-
(0...variables.size).each do |i|
|
99
|
-
@all << variables.inject([]) do |list, v|
|
100
|
-
list << (0...v.size).map do |j|
|
101
|
-
variables[i][j]
|
102
|
-
end
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
@all
|
107
|
-
|
108
|
-
|
109
|
-
v1 = [:spring, :summer, :fall, :winter]
|
110
|
-
v2 = [:true, :false]
|
111
|
-
a = [v1, v2]
|
112
|
-
b = []
|
113
|
-
a.each do |e|
|
114
|
-
b << e
|
115
|
-
end
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
=end
|
data/lib/fathom/archive/node.rb
DELETED
@@ -1,97 +0,0 @@
|
|
1
|
-
require 'rubygems'
|
2
|
-
require 'gsl'
|
3
|
-
|
4
|
-
include GSL
|
5
|
-
|
6
|
-
class Node
|
7
|
-
|
8
|
-
attr_reader :name, :labels, :probabilities, :likelihood
|
9
|
-
|
10
|
-
def initialize(*args)
|
11
|
-
@name = args.shift
|
12
|
-
raise ArgumentError, "Must provide a node name" unless self.name
|
13
|
-
if args.empty?
|
14
|
-
extract_from_array([:true, :false])
|
15
|
-
elsif args.length == 1 and args.first.is_a?(Hash)
|
16
|
-
extract_from_hash(args.first)
|
17
|
-
elsif args.length == 1 and args.first.is_a?(Array)
|
18
|
-
extract_from_array(args.first)
|
19
|
-
else
|
20
|
-
extract_from_array(args)
|
21
|
-
end
|
22
|
-
assert_likelihood
|
23
|
-
end
|
24
|
-
|
25
|
-
def inspect
|
26
|
-
matched_array = []
|
27
|
-
self.labels.each_with_index {|e, i| matched_array << e; matched_array << self.probabilities[i]}
|
28
|
-
"Node: #{self.name.to_s} #{self.labels.inspect} #{self.probabilities.to_a.inspect}"
|
29
|
-
"Node: #{self.name.to_s} #{matched_array.inspect}"
|
30
|
-
end
|
31
|
-
|
32
|
-
def belief
|
33
|
-
probabilities * likelihood
|
34
|
-
end
|
35
|
-
|
36
|
-
alias :b :belief
|
37
|
-
alias :l :likelihood
|
38
|
-
alias :p :probabilities
|
39
|
-
|
40
|
-
def probability(label)
|
41
|
-
probabilities[index_for(label)]
|
42
|
-
end
|
43
|
-
|
44
|
-
def inverse_probability(label)
|
45
|
-
1 - probability(label)
|
46
|
-
end
|
47
|
-
|
48
|
-
def odds(label)
|
49
|
-
probability(label) / inverse_probability(label)
|
50
|
-
end
|
51
|
-
|
52
|
-
def to_a
|
53
|
-
self.probabilities.to_a
|
54
|
-
end
|
55
|
-
|
56
|
-
protected
|
57
|
-
|
58
|
-
def index_for(label)
|
59
|
-
labels.index(label)
|
60
|
-
end
|
61
|
-
|
62
|
-
def assert_likelihood
|
63
|
-
@likelihood = Vector.ary_to_gv(Array.new(@probabilities.size, 1))
|
64
|
-
end
|
65
|
-
|
66
|
-
def extract_from_array(array)
|
67
|
-
@labels = array
|
68
|
-
@probabilities = Vector.ary_to_gv(uniform_distribution(array.size))
|
69
|
-
end
|
70
|
-
|
71
|
-
def uniform_distribution(n)
|
72
|
-
Array.new(n, 1/n.to_f)
|
73
|
-
end
|
74
|
-
|
75
|
-
def extract_from_hash(hash)
|
76
|
-
@labels, probabilities = [], []
|
77
|
-
hash.each do |k, v|
|
78
|
-
@labels << k
|
79
|
-
probabilities << v
|
80
|
-
end
|
81
|
-
@probabilities = Vector.ary_to_gv(probabilities)
|
82
|
-
normalize_probabilities!
|
83
|
-
end
|
84
|
-
|
85
|
-
# I don't like GSL::Vector#normalize!, it's not accurate, or has a different
|
86
|
-
# idea of what a normalized vector looks like.
|
87
|
-
def normalize_probabilities!
|
88
|
-
sum = 0.0
|
89
|
-
@probabilities.each do |value|
|
90
|
-
sum += value
|
91
|
-
end
|
92
|
-
@probabilities.map! do |value|
|
93
|
-
value.to_f / sum
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
end
|
@@ -1,136 +0,0 @@
|
|
1
|
-
=begin
|
2
|
-
I want to noodle around a bit with basic probabilities, odds, that sort of thing. Here's the example:
|
3
|
-
|
4
|
-
Upon being awakened by the sound of a burglar alary, what is your degree of belief that a burglary attempt took place?
|
5
|
-
|
6
|
-
Supporting information:
|
7
|
-
|
8
|
-
* There is a 95% chance that an attempted burglary will trigger the alarm system, P(alarm|burglary) = 95%
|
9
|
-
* There is a 1% chance that the alarms will be triggered by non-burglary attempts, p(alarm|no burglary) = 1%
|
10
|
-
* There is a 1/10_000 chance of a particular home being burglarized, generally, P(burglary) = 10^-4
|
11
|
-
|
12
|
-
O(burglary|alarm) = L(alarm|burglary)O(burglary)
|
13
|
-
|
14
|
-
P(burglary|alarm) = O(burglary|alarm) / 1 + O(burglary|alarm)
|
15
|
-
|
16
|
-
=end
|
17
|
-
|
18
|
-
require 'mathn'
|
19
|
-
|
20
|
-
def likelihood(effect, cause)
|
21
|
-
effect / cause
|
22
|
-
end
|
23
|
-
alias :l :likelihood
|
24
|
-
|
25
|
-
def odds(effect, cause=nil)
|
26
|
-
cause ? ( likelihood(cause, effect) * odds(effect) ) : (effect / (1 - effect))
|
27
|
-
end
|
28
|
-
alias :o :odds
|
29
|
-
|
30
|
-
# The same as the odds above, but only in the case of a single hypothesis
|
31
|
-
def prior_odds(e)
|
32
|
-
e / ( 1 - e )
|
33
|
-
end
|
34
|
-
|
35
|
-
def likelihood_ratio(e, h)
|
36
|
-
p(e,h) / p(e, 1 - h)
|
37
|
-
end
|
38
|
-
|
39
|
-
def probability(e, h)
|
40
|
-
(e * h) / h
|
41
|
-
end
|
42
|
-
|
43
|
-
def product_rule(*e)
|
44
|
-
end
|
45
|
-
alias :p :probability
|
46
|
-
|
47
|
-
class Array
|
48
|
-
|
49
|
-
def givens
|
50
|
-
@givens ||= {}
|
51
|
-
end
|
52
|
-
|
53
|
-
def give(sym, array=Array.new(self.size, 1/self.size))
|
54
|
-
self.givens[sym] = array
|
55
|
-
end
|
56
|
-
|
57
|
-
def given(sym, index)
|
58
|
-
self.givens[sym][index]
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
=begin
|
63
|
-
Since Rational is the automatic choice for probabilistic data,
|
64
|
-
and since I don't want to override how mathn infers numbers,
|
65
|
-
I am adding some baggage to Rational:
|
66
|
-
|
67
|
-
* It still reduces to the LCD
|
68
|
-
* It keeps track of all events,
|
69
|
-
so that I can keep a new event proportional to old ones
|
70
|
-
* It has an add_event (add) which takes a true or false value
|
71
|
-
true values, records that a condition was found
|
72
|
-
|
73
|
-
This really only works for binary data, but this is a noodle file.
|
74
|
-
|
75
|
-
=end
|
76
|
-
class Rational < Numeric
|
77
|
-
class << self
|
78
|
-
alias :orig_reduce :reduce
|
79
|
-
def reduce(num, den=1)
|
80
|
-
val = orig_reduce(num, den)
|
81
|
-
val.total_events = den
|
82
|
-
val.positive_events = num
|
83
|
-
val
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
def total_events(val=nil)
|
88
|
-
@total_events ||= 0
|
89
|
-
@total_events = val if val
|
90
|
-
@total_events
|
91
|
-
end
|
92
|
-
alias :events :total_events
|
93
|
-
alias :total :total_events
|
94
|
-
|
95
|
-
def total_events=(val)
|
96
|
-
total_events(val)
|
97
|
-
end
|
98
|
-
|
99
|
-
def positive_events(val=nil)
|
100
|
-
@positive_events ||= 0
|
101
|
-
@positive_events = val if val
|
102
|
-
@positive_events
|
103
|
-
end
|
104
|
-
alias :positive :positive_events
|
105
|
-
|
106
|
-
def positive_events=(val)
|
107
|
-
positive_events(val)
|
108
|
-
end
|
109
|
-
|
110
|
-
# Uses the Rational constructor to calculate the lowest common denominator
|
111
|
-
def add_event(positive=true)
|
112
|
-
num = positive ? self.positive_events + 1 : self.positive_events
|
113
|
-
den = self.total_events + 1
|
114
|
-
other = Rational(num, den)
|
115
|
-
@numerator, @denominator, @positive_events, @total_events = other.numerator, other.denominator, num, den
|
116
|
-
self
|
117
|
-
end
|
118
|
-
alias :add :add_event
|
119
|
-
end
|
120
|
-
|
121
|
-
|
122
|
-
class A
|
123
|
-
class << self
|
124
|
-
include GSL
|
125
|
-
|
126
|
-
def r
|
127
|
-
@r ||= Rng.alloc
|
128
|
-
end
|
129
|
-
|
130
|
-
def pdf
|
131
|
-
r = self.r.gaussian
|
132
|
-
pdf = Ran.gaussian_pdf(r)
|
133
|
-
puts r, pdf
|
134
|
-
end
|
135
|
-
end
|
136
|
-
end
|
@@ -1,45 +0,0 @@
|
|
1
|
-
require 'node'
|
2
|
-
require 'conditional_probability_matrix'
|
3
|
-
|
4
|
-
class A
|
5
|
-
class << self
|
6
|
-
# def will_pay
|
7
|
-
# @will_pay ||= Node.new :true, :false
|
8
|
-
# end
|
9
|
-
#
|
10
|
-
# def has_money
|
11
|
-
# @has_money ||= Node.new :plenty => 0.1, :some => 0.8, :little => 0.1
|
12
|
-
# end
|
13
|
-
#
|
14
|
-
# def ones
|
15
|
-
# Matrix.ones(will_pay.values.length, has_money.values.length)
|
16
|
-
# end
|
17
|
-
#
|
18
|
-
# def parents
|
19
|
-
# will_pay.values.col * has_money.values
|
20
|
-
# # will_pay.each do |value|
|
21
|
-
# #
|
22
|
-
# # end
|
23
|
-
# end
|
24
|
-
#
|
25
|
-
# def cpm
|
26
|
-
# ConditionalProbabilityMatrix.new(will_pay, has_money)
|
27
|
-
# end
|
28
|
-
|
29
|
-
def killer_identity
|
30
|
-
@killer_identity ||= Node.new(:killer_identity, :jack => 0.8, :joe => 0.1, :jeff => 0.1)
|
31
|
-
end
|
32
|
-
alias :k :killer_identity
|
33
|
-
alias :x :killer_identity
|
34
|
-
|
35
|
-
def fingerprint_information
|
36
|
-
@fingerprint_information ||= Node.new(:fingerprint_information, :jack => 2/3.0, :joe => 1/6.0, :jeff => 1/6.0)
|
37
|
-
end
|
38
|
-
alias :f :fingerprint_information
|
39
|
-
alias :y :fingerprint_information
|
40
|
-
|
41
|
-
def cpm
|
42
|
-
@cpm ||= ConditionalProbabilityMatrix.new(x, y)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
data/lib/fathom/distributions.rb
DELETED
@@ -1,44 +0,0 @@
|
|
1
|
-
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'fathom'))
|
2
|
-
class Fathom::Distributions::DiscreteGaussian
|
3
|
-
extend Fathom::Distributions::SharedMethods
|
4
|
-
class << self
|
5
|
-
def rng
|
6
|
-
@rng ||= GSL::Rng.alloc(GSL::Rng::MT19937_1999, Kernel.rand(100_000))
|
7
|
-
end
|
8
|
-
|
9
|
-
def rand(sd)
|
10
|
-
(rng.gaussian(sd) / size).floor + 1
|
11
|
-
end
|
12
|
-
|
13
|
-
def inverse_cdf(opts={})
|
14
|
-
mean = opts[:mean]
|
15
|
-
sd = opts[:sd]
|
16
|
-
sd ||= opts[:std]
|
17
|
-
sd ||= opts[:standard_deviation]
|
18
|
-
lower = opts.fetch(:lower, true)
|
19
|
-
lower = false if opts[:upper]
|
20
|
-
confidence_interval = opts.fetch(:confidence_interval, 0.05)
|
21
|
-
value = lower ? GSL::Cdf.gaussian_Pinv(confidence_interval, sd) : GSL::Cdf.gaussian_Qinv(confidence_interval, sd)
|
22
|
-
value + mean
|
23
|
-
end
|
24
|
-
alias :lower_bound :inverse_cdf
|
25
|
-
|
26
|
-
def upper_bound(opts={})
|
27
|
-
inverse_cdf(opts.merge(:lower => false))
|
28
|
-
end
|
29
|
-
|
30
|
-
def interval_values(opts={})
|
31
|
-
confidence_interval = opts.fetch(:confidence_interval, 0.9)
|
32
|
-
bound = (1 - confidence_interval) / 2.0
|
33
|
-
[lower_bound(opts.merge(:confidence_interval => bound)), upper_bound(opts.merge(:confidence_interval => bound))]
|
34
|
-
end
|
35
|
-
|
36
|
-
# If only I had the background to explain what this is....
|
37
|
-
# I want to know how many standard deviations are expressed by the confidence interval
|
38
|
-
# I can then divide the range by this number to get the standard deviation
|
39
|
-
def standard_deviations_under(confidence_interval)
|
40
|
-
GSL::Cdf.gaussian_Qinv((1 - confidence_interval) / 2) * 2
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|