fathom 0.3.7 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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