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.
Files changed (134) hide show
  1. data/.autotest +7 -5
  2. data/.document +2 -2
  3. data/Gemfile +9 -10
  4. data/{LICENSE → LICENSE.txt} +1 -1
  5. data/README.md +29 -90
  6. data/Rakefile +34 -32
  7. data/VERSION +1 -1
  8. data/fathom.gemspec +105 -0
  9. data/features/fathom.feature +26 -0
  10. data/features/step_definitions/fathom_steps.rb +23 -0
  11. data/features/support/env.rb +13 -0
  12. data/lib/ext/array.rb +6 -2
  13. data/lib/ext/string.rb +86 -7
  14. data/lib/fathom.rb +51 -88
  15. data/lib/fathom/behaviors/attribute_system.rb +91 -0
  16. data/lib/fathom/behaviors/context_behavior.rb +28 -0
  17. data/lib/fathom/behaviors/plugins.rb +16 -0
  18. data/lib/fathom/contexts/network_population.rb +47 -0
  19. data/lib/fathom/contexts/network_traversal.rb +4 -0
  20. data/lib/fathom/data/adjacency_matrix.rb +27 -0
  21. data/lib/fathom/data/definition.rb +22 -0
  22. data/lib/fathom/data/edge.rb +58 -0
  23. data/lib/fathom/data/network.rb +35 -0
  24. data/lib/fathom/data/outcome.rb +30 -0
  25. data/lib/fathom/data/property.rb +31 -0
  26. data/lib/fathom/data/variable.rb +59 -0
  27. data/lib/fathom/roles/general_graph_tools.rb +87 -0
  28. data/lib/fathom/roles/network_builder.rb +61 -0
  29. data/spec/fathom/behaviors/attribute_system_spec.rb +141 -0
  30. data/spec/fathom/behaviors/context_behavior_spec.rb +15 -0
  31. data/spec/fathom/behaviors/plugins_spec.rb +80 -0
  32. data/spec/fathom/contexts/network_population_spec.rb +55 -0
  33. data/spec/fathom/contexts/network_traversal_spec.rb +11 -0
  34. data/spec/fathom/data/adjacency_matrix_spec.rb +42 -0
  35. data/spec/fathom/data/definition_spec.rb +19 -0
  36. data/spec/fathom/data/edge_spec.rb +77 -0
  37. data/spec/fathom/data/network_spec.rb +72 -0
  38. data/spec/fathom/data/outcome_spec.rb +17 -0
  39. data/spec/fathom/data/property_spec.rb +17 -0
  40. data/spec/fathom/data/variable_spec.rb +101 -0
  41. data/spec/fathom/ext/array_spec.rb +17 -0
  42. data/spec/fathom/ext/string_spec.rb +90 -0
  43. data/spec/fathom/roles/general_graph_tools_spec.rb +95 -0
  44. data/spec/fathom/roles/network_builder_spec.rb +90 -0
  45. data/spec/fathom_spec.rb +28 -49
  46. data/spec/spec_helper.rb +7 -11
  47. data/spec/support/context_behavior.rb +14 -0
  48. data/spec/support/custom_matchers.rb +12 -0
  49. data/spec/support/files.rb +8 -0
  50. data/spec/support/network.yml +42 -0
  51. metadata +133 -174
  52. data/.bundle/config +0 -2
  53. data/.gitignore +0 -6
  54. data/Gemfile.lock +0 -42
  55. data/TODO.md +0 -127
  56. data/autotest/discover.rb +0 -1
  57. data/lib/ext/faster_csv.rb +0 -1
  58. data/lib/ext/open_struct.rb +0 -17
  59. data/lib/fathom/agent.rb +0 -48
  60. data/lib/fathom/agent/agent_cluster.rb +0 -23
  61. data/lib/fathom/agent/properties.rb +0 -48
  62. data/lib/fathom/archive/causal_graph.rb +0 -12
  63. data/lib/fathom/archive/concept.rb +0 -83
  64. data/lib/fathom/archive/conditional_probability_matrix.rb +0 -119
  65. data/lib/fathom/archive/inverter.rb +0 -20
  66. data/lib/fathom/archive/n2.rb +0 -198
  67. data/lib/fathom/archive/n3.rb +0 -119
  68. data/lib/fathom/archive/node.rb +0 -97
  69. data/lib/fathom/archive/noodle.rb +0 -136
  70. data/lib/fathom/archive/scratch.rb +0 -45
  71. data/lib/fathom/distributions.rb +0 -8
  72. data/lib/fathom/distributions/discrete_gaussian.rb +0 -44
  73. data/lib/fathom/distributions/discrete_uniform.rb +0 -25
  74. data/lib/fathom/distributions/gaussian.rb +0 -46
  75. data/lib/fathom/distributions/uniform.rb +0 -35
  76. data/lib/fathom/import.rb +0 -85
  77. data/lib/fathom/import/csv_import.rb +0 -59
  78. data/lib/fathom/import/import_node.rb +0 -17
  79. data/lib/fathom/import/yaml_import.rb +0 -74
  80. data/lib/fathom/knowledge_base.rb +0 -46
  81. data/lib/fathom/knowledge_base/search.rb +0 -19
  82. data/lib/fathom/monte_carlo_set.rb +0 -152
  83. data/lib/fathom/node.rb +0 -139
  84. data/lib/fathom/node/belief_node.rb +0 -121
  85. data/lib/fathom/node/cpm_node.rb +0 -100
  86. data/lib/fathom/node/data_collection.rb +0 -97
  87. data/lib/fathom/node/data_node.rb +0 -22
  88. data/lib/fathom/node/decision.rb +0 -11
  89. data/lib/fathom/node/discrete_node.rb +0 -41
  90. data/lib/fathom/node/fact.rb +0 -24
  91. data/lib/fathom/node/mc_node.rb +0 -70
  92. data/lib/fathom/node/node_extensions/enforced_name.rb +0 -12
  93. data/lib/fathom/node/node_extensions/numeric_methods.rb +0 -68
  94. data/lib/fathom/node/plausible_range.rb +0 -98
  95. data/lib/fathom/simulation.rb +0 -59
  96. data/lib/fathom/simulation/tick_methods.rb +0 -25
  97. data/lib/fathom/simulation/tick_simulation.rb +0 -12
  98. data/lib/fathom/value_description.rb +0 -79
  99. data/lib/options_hash.rb +0 -186
  100. data/spec/ext/array_spec.rb +0 -10
  101. data/spec/ext/faster_csv_spec.rb +0 -10
  102. data/spec/ext/open_struct_spec.rb +0 -20
  103. data/spec/ext/string_spec.rb +0 -7
  104. data/spec/fathom/agent/agent_cluster_spec.rb +0 -17
  105. data/spec/fathom/agent_spec.rb +0 -51
  106. data/spec/fathom/distributions/discrete_gaussian_spec.rb +0 -64
  107. data/spec/fathom/distributions/discrete_uniform_spec.rb +0 -0
  108. data/spec/fathom/distributions/gaussian_spec.rb +0 -64
  109. data/spec/fathom/distributions/uniform_spec.rb +0 -0
  110. data/spec/fathom/import/csv_import_spec.rb +0 -52
  111. data/spec/fathom/import/import_node_spec.rb +0 -10
  112. data/spec/fathom/import/yaml_import_spec.rb +0 -73
  113. data/spec/fathom/import_spec.rb +0 -36
  114. data/spec/fathom/knowledge_base_spec.rb +0 -20
  115. data/spec/fathom/monte_carlo_set_spec.rb +0 -149
  116. data/spec/fathom/node/belief_node_spec.rb +0 -180
  117. data/spec/fathom/node/cpm_node_spec.rb +0 -144
  118. data/spec/fathom/node/data_collection_spec.rb +0 -26
  119. data/spec/fathom/node/data_node_spec.rb +0 -102
  120. data/spec/fathom/node/decision_spec.rb +0 -15
  121. data/spec/fathom/node/discrete_node_spec.rb +0 -56
  122. data/spec/fathom/node/fact_spec.rb +0 -33
  123. data/spec/fathom/node/mc_node_spec.rb +0 -66
  124. data/spec/fathom/node/node_extensions/enforced_name_spec.rb +0 -15
  125. data/spec/fathom/node/node_extensions/numeric_methods_spec.rb +0 -124
  126. data/spec/fathom/node/plausible_range_spec.rb +0 -151
  127. data/spec/fathom/node_spec.rb +0 -172
  128. data/spec/fathom/simulation/tick_simulation_spec.rb +0 -32
  129. data/spec/fathom/simulation_spec.rb +0 -24
  130. data/spec/fathom/value_description_spec.rb +0 -70
  131. data/spec/support/demo.yml +0 -17
  132. data/spec/support/demo_agent.rb +0 -8
  133. data/spec/support/dummy_numeric_node.rb +0 -8
  134. data/spec/support/fact.yml +0 -11
@@ -1,25 +0,0 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'fathom'))
2
- class Fathom::Distributions::DiscreteUniform
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
- # Bounded from 0 to size - 1
10
- def rand(size)
11
- value = get_rand(size)
12
- while value < 0 or value >= size
13
- value = get_rand(size)
14
- end
15
- value
16
- end
17
-
18
- protected
19
- def get_rand(size)
20
- (rng.ugaussian / size).floor + 1
21
- end
22
-
23
- end
24
- end
25
-
@@ -1,46 +0,0 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'fathom'))
2
- class Fathom::Distributions::Gaussian
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)
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
-
43
-
44
- end
45
- end
46
-
@@ -1,35 +0,0 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'fathom'))
2
- class Fathom::Distributions::Uniform
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
10
- rng.ugaussian
11
- end
12
-
13
- def inverse_cdf(opts={})
14
- mean = opts[:mean]
15
- lower = opts.fetch(:lower, true)
16
- lower = false if opts[:upper]
17
- confidence_interval = opts.fetch(:confidence_interval, 0.05)
18
- value = lower ? GSL::Cdf.ugaussian_Pinv(confidence_interval) : GSL::Cdf.ugaussian_Qinv(confidence_interval)
19
- value + mean
20
- end
21
- alias :lower_bound :inverse_cdf
22
-
23
- def upper_bound(opts={})
24
- inverse_cdf(opts.merge(:lower => false))
25
- end
26
-
27
- def interval_values(opts={})
28
- confidence_interval = opts.fetch(:confidence_interval, 0.9)
29
- bound = (1 - confidence_interval) / 2.0
30
- [lower_bound(opts.merge(:confidence_interval => bound)), upper_bound(opts.merge(:confidence_interval => bound))]
31
- end
32
-
33
- end
34
- end
35
-
@@ -1,85 +0,0 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), '..', 'fathom'))
2
-
3
- =begin
4
-
5
- The import scripts are meant to make it easier to build up a knowledge base from
6
- real data. There are a lot of ways we could get our data: YAML files, spreadsheets,
7
- web crawlers, relational databases, RDF data. The Import class creates a regular
8
- way to create nodes in the knowledge base. The following example would be a
9
- simple way to import some data about weekend trips:
10
-
11
- class WeekendPlanningImport < Import
12
- def import_plausible_data
13
- values = [
14
- {:name => 'Chance of Rain', :min => 0.2, :max => 0.3, :confidence_interval => 0.8},
15
- {:name => 'Would Go to the Beach Despite the Rain', :min => 0, :max => 0.2},
16
- {:name => 'Would Go to the Movies if Something Good Was Playing', :min => 0.8, :max => 1.0},
17
- {:name => 'Would Go to the Movies Despite the Rain', :min => 0.9, :max => 1.0}
18
- ]
19
- return [PlausibleRange, values]
20
- end
21
-
22
- def import_destination_data
23
- value_hash = FasterCSV...
24
- return [DataNode, value_hash]
25
- end
26
- end
27
-
28
- Each import method is starts with 'import_' and returns an array of [NodeClass, values_hash].
29
- The Import class will then create a series of nodes and insert them into the active knowledge
30
- base.
31
-
32
- There are a number of useful Import classes that make most data imports fairly straight forward.
33
- This way data from spreadsheets or YAML files can easily be added to the knowledge base.
34
-
35
- =end
36
-
37
- module Fathom
38
- class Import
39
-
40
- class << self
41
- def import(opts={})
42
- importer = new(opts)
43
- importer.import
44
- end
45
- end
46
-
47
- attr_reader :content, :options, :import_node
48
-
49
- def initialize(opts={})
50
- @options = OptionsHash.new(opts)
51
- @content = @options[:content]
52
- @import_node = ImportNode.new(opts)
53
- end
54
-
55
- def import
56
- import_methods.each do |method|
57
- klass, initialization_data = self.send(method.to_sym)
58
- initialization_data.each do |values|
59
- extract_nodes(klass, values)
60
- end
61
- end
62
- self.import_node
63
- end
64
-
65
- protected
66
-
67
- # Just blankly try to initiate a node. If it fails, silently fail for now.
68
- def extract_nodes(klass, values)
69
- begin
70
- node = klass.new(values)
71
- if node
72
- self.import_node.add_child(node)
73
- Fathom.knowledge_base[node.name] = node
74
- end
75
- rescue
76
- nil
77
- end
78
- end
79
-
80
- def import_methods
81
- (self.methods - self.class.superclass.instance_methods).map {|m| m if m =~ /import_\w+/}.compact
82
- end
83
-
84
- end
85
- end
@@ -1,59 +0,0 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'fathom'))
2
- require 'import'
3
- require 'open-uri'
4
-
5
- # TODO: Work this out with Ruby 1.9. We don't need to load this for all Rubies.
6
- require 'fastercsv'
7
- require 'ext/faster_csv'
8
-
9
- module Fathom
10
- class CSVImport < Import
11
-
12
- # @content could be a filename, URI, or actual file contents. We figure out which
13
- # it is and then parse the contents with FasterCSV. We assume that there are column
14
- # headers that are the names of each node, and that the values in the node are
15
- # values for a DataNode.
16
- def import_csv
17
- parsed = parse_contents
18
- extracted = extract_columns(parsed)
19
- [DataNode, extracted]
20
- end
21
-
22
- # These are the options we use to parse the file. They can be overriden
23
- # by calling CSVImport.new(:parse_options => {...}, ...)
24
- def parse_options
25
- return @parse_options if @parse_options
26
- @parse_options = @options[:parse_options]
27
- @parse_options ||= {:converters => [:all], :headers => true, :skip_blanks => true, :header_converters => [:strip, :symbol]}
28
- @parse_options
29
- end
30
-
31
- protected
32
- def parse_contents
33
- arr_of_arrs = FasterCSV.parse(get_contents, parse_options)
34
- end
35
-
36
- # Tries to read a file or URL. That failing, assumes the contents are CSV contents.
37
- def get_contents
38
- begin
39
- content = open(@content).read
40
- rescue
41
- content = @content
42
- end
43
- return content
44
- end
45
-
46
- # Returns an array of hashes with :name => row header, :values => values
47
- def extract_columns(parsed)
48
- transposed = parsed.to_a.transpose
49
- transposed.inject([]) do |list, column|
50
- list << {:name => column.shift, :values => column}
51
- end
52
- end
53
-
54
- end
55
- end
56
-
57
- if __FILE__ == $0
58
- Fathom::CSVImport.import(:content => ARGV.first)
59
- end
@@ -1,17 +0,0 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'fathom'))
2
- class Fathom::ImportNode < Fathom::Node
3
-
4
- attr_reader :imported_at
5
-
6
- def initialize(opts={})
7
- super(opts)
8
- @imported_at = Time.now
9
- end
10
-
11
- end
12
-
13
- if __FILE__ == $0
14
- include Fathom
15
- # TODO: Is there anything you want to do to run this file on its own?
16
- # ImportNode.new
17
- end
@@ -1,74 +0,0 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'fathom'))
2
- require 'open-uri'
3
- require 'yaml'
4
-
5
- class Fathom::YAMLImport < Fathom::Import
6
- def import_plausible_ranges
7
- assert_yaml_content
8
- plausible_ranges = extract_plausible_ranges
9
- [PlausibleRange, plausible_ranges]
10
- end
11
-
12
- def import_data_nodes
13
- assert_yaml_content
14
- data_nodes = extract_data_nodes
15
- [DataNode, data_nodes]
16
- end
17
-
18
- def import_facts
19
- assert_yaml_content
20
- facts = extract_facts
21
- [Fact, facts]
22
- end
23
-
24
- protected
25
- def assert_yaml_content
26
- return @yaml_content if @yaml_content
27
- begin
28
- file_contents = open(self.content).read
29
- raise ArgumentError, "Unable to extract YAML data out of the contents." unless file_contents
30
- rescue
31
- file_contents = self.content
32
- end
33
- @yaml_content = YAML.load(file_contents)
34
- end
35
-
36
- def extract_facts
37
- return [] unless @yaml_content
38
- output = []
39
- @yaml_content.each do |e|
40
- next unless e.is_a?(Array)
41
- next unless e.first.to_s.match(/fact/i)
42
- obj = e[1]
43
- next unless obj.is_a?(Hash)
44
- output << obj
45
- end
46
- output
47
- end
48
-
49
- def extract_plausible_ranges
50
- return [] unless @yaml_content
51
- @yaml_content.inject([]) do |list, array|
52
- name, value = array.first, array.last
53
- if value.is_a?(Hash)
54
- value = OptionsHash.new(value)
55
- # list << value.merge(:name => name) if value[:min] and value[:max]
56
- list << value.merge(:name => name)
57
- end
58
- list
59
- end
60
- end
61
-
62
- def extract_data_nodes
63
- return [] unless @yaml_content
64
- @yaml_content.inject([]) do |list, array|
65
- name, value = array.first, array.last
66
- list << {:name => name, :values => value} if value.is_a?(Array)
67
- list
68
- end
69
- end
70
- end
71
-
72
- if __FILE__ == $0
73
- Fathom::YAMLImport.import(:content => ARGV.first)
74
- end
@@ -1,46 +0,0 @@
1
- require File.expand_path("../../fathom", __FILE__)
2
-
3
- require 'rdf'
4
- require 'knowledge_base/search'
5
-
6
- module Fathom
7
- class KnowledgeBase
8
-
9
- # =====================
10
- # = Module Extensions =
11
- # =====================
12
- include Search
13
-
14
- # attr_reader :data_store
15
-
16
- def initialize(opts={})
17
- # opts = OptionsHash.new(opts)
18
- # @data_store = OpenStruct.new
19
- end
20
-
21
- # def []=(key, value)
22
- # @data_store.table[key] = value
23
- # end
24
- #
25
- # def [](key)
26
- # @data_store.table[key]
27
- # end
28
- #
29
- # # This is temporary, but useful for now. After we have the persisted KnowledgeBase,
30
- # # we'll create explicit accessor methods or a find syntax.
31
- # def method_missing(sym, *args, &block)
32
- # if @data_store.table.keys.include?(sym)
33
- # @data_store.send(sym)
34
- # else
35
- # super
36
- # end
37
- # end
38
-
39
- end
40
- end
41
-
42
- if __FILE__ == $0
43
- include Fathom
44
- # TODO: Is there anything you want to do to run this file on its own?
45
- # KnowledgeBase.new
46
- end
@@ -1,19 +0,0 @@
1
- require 'sparql/algebra'
2
-
3
- module Fathom
4
- module Search
5
-
6
- def self.included(base)
7
- base.send(:extend, ClassMethods)
8
- base.send(:include, InstanceMethods)
9
- end
10
-
11
- module ClassMethods
12
- def find(opts={})
13
- end
14
- end
15
-
16
- module InstanceMethods
17
- end
18
- end
19
- end
@@ -1,152 +0,0 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), '..', 'fathom'))
2
- class Fathom::MonteCarloSet
3
-
4
- class << self
5
- def define_key(key)
6
- define_method(key.to_sym) do
7
- self.samples[key.to_sym]
8
- end
9
- end
10
-
11
- def define_summary_method(field)
12
- define_method("#{field}_summary".to_sym) do
13
- self.summary(field.to_sym)
14
- end
15
- end
16
- end
17
-
18
- attr_reader :value_description, :samples_taken, :samples
19
-
20
- def initialize(value_description)
21
- @value_description = value_description
22
- @samples = {}
23
- end
24
-
25
- def process(n=10_000)
26
- @samples_taken = n
27
- @samples_taken.times do
28
- result = value_description.process
29
- store(result)
30
- end
31
- assert_sample_vectors
32
- end
33
-
34
- def reset!
35
- @samples = {}
36
- @keys_asserted = nil
37
- end
38
-
39
- def fields
40
- @samples.keys
41
- end
42
-
43
- def summary(field=nil)
44
- return summarize_field(field) if field
45
- fields.inject({}) do |h, field|
46
- h[field] = summarize_field(field)
47
- h
48
- end
49
- end
50
-
51
- def print_summary
52
- print_hash(self.summary)
53
- end
54
-
55
- protected
56
-
57
- def print_hash(hash, indent=0)
58
- hash.each do |key, value|
59
- if value.is_a?(Hash)
60
- puts "#{' ' * indent}#{key} => {"
61
- print_hash(value, indent + 2)
62
- puts "#{' ' * indent}}"
63
- else
64
- puts "#{' ' * indent}#{key} => #{value}"
65
- end
66
- end
67
- end
68
-
69
- def summarize_field(field)
70
- raise "No fields are defined. Have you processed this model yet?" if fields.empty?
71
- raise ArgumentError, "#{field} is not a field in this set." unless fields.include?(field)
72
- vector = self.send(field)
73
- return vector unless vector.is_a?(GSL::Vector)
74
- lb = lower_bound(:mean => vector.mean, :sd => vector.sd)
75
- lb = vector.min if vector.min > lb
76
- ub = upper_bound(:mean => vector.mean, :sd => vector.sd)
77
- ub = vector.max if vector.max < ub
78
-
79
- {
80
- :coefficient_of_variation => (vector.sd / vector.mean),
81
- :max => vector.max,
82
- :mean => vector.mean,
83
- :min => vector.min,
84
- :sd => vector.sd,
85
- :upper_bound => ub,
86
- :lower_bound => lb
87
- }
88
- end
89
-
90
- def inverse_cdf(opts={})
91
- mean = opts[:mean]
92
- sd = opts[:sd]
93
- lower = opts.fetch(:lower, true)
94
- confidence_interval = opts.fetch(:confidence_interval, 0.05)
95
- value = lower ? GSL::Cdf.gaussian_Pinv(confidence_interval, sd) : GSL::Cdf.gaussian_Qinv(confidence_interval, sd)
96
- value + mean
97
- end
98
- alias :lower_bound :inverse_cdf
99
-
100
- def upper_bound(opts={})
101
- inverse_cdf(opts.merge(:lower => false))
102
- end
103
-
104
- def interval_values(opts={})
105
- confidence_interval = opts.fetch(:confidence_interval, 0.9)
106
- bound = (1 - confidence_interval) / 2.0
107
- [lower_bound(opts.merge(:confidence_interval, bound)), upper_bound(opts.merge(:confidence_interval, bound))]
108
- end
109
-
110
- def assert_sample_vectors
111
- vectors = @samples.inject({}) do |h, o|
112
- key, obj = o.first, o.last
113
- h[key] = (obj.is_a?(Array) and obj.first.is_a?(Numeric)) ? GSL::Vector.ary_to_gv(obj) : obj
114
- h
115
- end
116
- @samples = vectors
117
- end
118
-
119
- def store(result)
120
- result = assert_result_hash(result)
121
- assert_keys(result)
122
- result.each do |key, value|
123
- @samples[key.to_sym] << value
124
- end
125
- end
126
-
127
- def assert_result_hash(result)
128
- result.is_a?(Hash) ? result : {:result => result}
129
- end
130
-
131
- # Assumes the same value description for all samples taken
132
- def assert_keys(result)
133
- return true if @keys_asserted
134
- result.keys.each do |key|
135
- assert_key(key)
136
- self.class.define_summary_method(key)
137
- end
138
- @keys_asserted = true
139
- end
140
-
141
- def assert_key(key)
142
- self.class.define_key(key)
143
- @samples[key.to_sym] ||= []
144
- end
145
-
146
- end
147
-
148
- if __FILE__ == $0
149
- include Fathom
150
- # TODO: Is there anything you want to do to run this file on its own?
151
- # MonteCarloSet.new
152
- end