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,22 +0,0 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'fathom'))
2
-
3
- =begin
4
- A DataNode is a node generated from data itself. It stores the data and reveals some statistical
5
- measurements for the data. It expects an array or vector of values and generates a vector on demans.
6
- =end
7
- class Fathom::DataNode < Fathom::Node
8
-
9
- include Fathom::NumericMethods
10
-
11
- def initialize(opts={})
12
- super(opts)
13
- raise ArgumentError, "Must provided values: DataNode.new(:values => [...])" unless self.values
14
- end
15
-
16
- end
17
-
18
- if __FILE__ == $0
19
- include Fathom
20
- # TODO: Is there anything you want to do to run this file on its own?
21
- # DataNode.new
22
- end
@@ -1,11 +0,0 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'fathom'))
2
- class Fathom::Decision < Fathom::Node
3
- undef_method :values
4
- undef_method :distribution
5
- end
6
-
7
- if __FILE__ == $0
8
- include Fathom
9
- # TODO: Is there anything you want to do to run this file on its own?
10
- # Decision.new
11
- end
@@ -1,41 +0,0 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'fathom'))
2
- class Fathom::DiscreteNode < Fathom::Node
3
- attr_reader :labels
4
-
5
- def initialize(opts={})
6
- opts[:distribution] ||= :discrete_uniform
7
- super(opts)
8
- assert_labels(opts)
9
- end
10
-
11
- def size
12
- @size ||= self.labels.length
13
- end
14
- alias :length :size
15
-
16
- def rand
17
- self.labels[self.distribution.rand(self.size)]
18
- end
19
-
20
- # This makes it easier to interface to a belief node
21
- def likelihood(ignored_value)
22
- GSL::Vector.ary_to_gv(Array.new(self.size, 1))
23
- end
24
- alias :l :likelihood
25
-
26
- protected
27
- def assert_labels(opts)
28
- @labels = opts[:labels]
29
- @labels ||= self.values
30
- @labels ||= [:true, :false]
31
- @labels = Array[@labels] unless @labels.is_a?(Array)
32
- @labels.uniq!
33
- end
34
-
35
- end
36
-
37
- if __FILE__ == $0
38
- include Fathom
39
- # TODO: Is there anything you want to do to run this file on its own?
40
- # DiscreteNode.new
41
- end
@@ -1,24 +0,0 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'fathom'))
2
- class Fathom::Fact < Fathom::Node
3
-
4
- attr_reader :value
5
-
6
- def initialize(opts={})
7
- symbolize_keys!(opts)
8
- @value = opts[:value]
9
- @value ||= opts[:values]
10
- super(opts)
11
- end
12
-
13
- alias :rand :value
14
-
15
- undef_method :values
16
- undef_method :distribution
17
-
18
- end
19
-
20
- if __FILE__ == $0
21
- include Fathom
22
- # TODO: Is there anything you want to do to run this file on its own?
23
- # Fact.new
24
- end
@@ -1,70 +0,0 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'fathom'))
2
- class Fathom::MCNode < Fathom::Node
3
-
4
- attr_reader :samples_taken
5
- attr_accessor :value_description
6
-
7
- def initialize(opts={}, &block)
8
- super(opts)
9
- @value_description = opts[:value_description]
10
- @value_description ||= block if block_given?
11
- raise ArgumentError, "Must provide a value_description from either a parameter or by passing in a block" unless
12
- @value_description
13
- end
14
-
15
- def process(n=10_000)
16
- @samples_taken, @samples = n, {}
17
- @samples_taken.times do
18
- result = value_description.call(self)
19
- store(result)
20
- end
21
- assert_nodes
22
- end
23
-
24
- def reset!
25
- @samples_taken, @samples = nil, {}
26
- @samples_asserted = false
27
- end
28
-
29
- def fields
30
- self.children.map {|c| c.name_sym}.compact
31
- end
32
-
33
- protected
34
-
35
- def store(result)
36
- result = assert_result_hash(result)
37
- assert_samples(result)
38
- result.each do |key, value|
39
- @samples[key.to_sym] << value
40
- end
41
- end
42
-
43
- def assert_samples(result)
44
- return true if @samples_asserted
45
- result.each do |k, v|
46
- @samples[k.to_sym] ||= []
47
- end
48
- @samples_asserted = true
49
- end
50
-
51
- def assert_result_hash(result)
52
- result.is_a?(Hash) ? result : {:result => result}
53
- end
54
-
55
- # Assumes the same value description for all samples taken
56
- def assert_nodes
57
- @samples.each do |key, values|
58
- node = Fathom::DataNode.new(:name => key, :values => values)
59
- add_child(node)
60
- # self.class.define_summary_method(key)
61
- end
62
- end
63
-
64
- end
65
-
66
- if __FILE__ == $0
67
- include Fathom
68
- # TODO: Is there anything you want to do to run this file on its own?
69
- # MCNode.new
70
- end
@@ -1,12 +0,0 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'fathom'))
2
- require 'uuid'
3
-
4
- module Fathom
5
- module EnforcedName
6
- def initialize(opts={})
7
- super(opts)
8
- @name ||= UUID.generate
9
- end
10
- end
11
- end
12
-
@@ -1,68 +0,0 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'fathom'))
2
- module Fathom
3
- module NumericMethods
4
- def initialize(opts={})
5
- super(opts)
6
- end
7
-
8
- def rand
9
- return nil unless vector
10
- distribution.rand(sd) + mean
11
- end
12
-
13
- def vector
14
- return @vector if @vector
15
- return nil unless values
16
- case values
17
- when Array
18
- @vector = GSL::Vector.ary_to_gv(values)
19
- when GSL::Vector
20
- @vector = values
21
- end
22
- end
23
-
24
- def standard_deviation
25
- return nil unless vector
26
- vector.sd
27
- end
28
- alias :std :standard_deviation
29
- alias :sd :standard_deviation
30
-
31
- def mean
32
- return nil unless vector
33
- vector.mean
34
- end
35
-
36
- def inverse_cdf(opts={})
37
- distribution.inverse_cdf(opts.merge(:mean => mean, :sd => sd))
38
- end
39
- alias :lower_bound :inverse_cdf
40
-
41
- def upper_bound(opts={})
42
- distribution.upper_bound(opts.merge(:mean => mean, :sd => sd))
43
- end
44
-
45
- def interval_values(opts={})
46
- distribution.interval_values(opts.merge(:mean => mean, :sd => sd))
47
- end
48
-
49
- def coefficient_of_variation
50
- return nil unless vector
51
- vector.sd / vector.mean
52
- end
53
- alias :cov :coefficient_of_variation
54
-
55
- def summary
56
- {
57
- :mean => mean,
58
- :standard_deviation => standard_deviation,
59
- :min => vector ? vector.min : nil,
60
- :max => vector ? vector.max : nil,
61
- :lower_bound => lower_bound,
62
- :upper_bound => upper_bound,
63
- :coefficient_of_variation => coefficient_of_variation
64
- }
65
- end
66
-
67
- end
68
- end
@@ -1,98 +0,0 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'fathom'))
2
- module Fathom
3
- class PlausibleRange < Fathom::Node
4
-
5
- include NumericMethods
6
-
7
- attr_reader :upper_bound, :lower_bound, :confidence_interval, :hard_lower_bound, :hard_upper_bound
8
-
9
- def initialize(opts={})
10
- super(opts)
11
-
12
- opts = OptionsHash.new(opts)
13
-
14
- @hard_upper_bound = opts[:hard_upper_bound]
15
- @upper_bound = opts[:upper_bound]
16
- @upper_bound ||= opts[:max]
17
- @upper_bound ||= @hard_upper_bound
18
- @upper_bound = @hard_upper_bound if @upper_bound and @hard_upper_bound and @hard_upper_bound < @upper_bound
19
- raise ArgumentError, "Must provide an upper bound." unless @upper_bound
20
-
21
- @hard_lower_bound = opts[:hard_lower_bound]
22
- @lower_bound = opts[:lower_bound]
23
- @lower_bound ||= opts[:min]
24
- @lower_bound ||= @hard_lower_bound
25
- @lower_bound = @hard_lower_bound if @lower_bound and @hard_lower_bound and @hard_lower_bound > @lower_bound
26
- raise ArgumentError, "Must provide a lower bound." unless @lower_bound
27
-
28
- @confidence_interval = opts[:confidence_interval]
29
- @confidence_interval ||= opts[:ci]
30
- @confidence_interval ||= 0.9
31
-
32
- end
33
-
34
- alias :min :lower_bound
35
- alias :max :upper_bound
36
- alias :ci :confidence_interval
37
-
38
- def midpoint
39
- @midpoint ||= lower_bound + (range / 2.0)
40
- end
41
- alias :mean :midpoint
42
-
43
- def range
44
- @range ||= upper_bound - lower_bound
45
- end
46
-
47
- def standard_deviation
48
- @standard_deviation ||= range / distribution.standard_deviations_under(confidence_interval)
49
- end
50
- alias :std :standard_deviation
51
- alias :sd :standard_deviation
52
-
53
- def rand
54
- value = get_rand
55
- until is_bounded?(value) do
56
- value = get_rand
57
- end
58
- value
59
- end
60
-
61
- def array_of_random_values(n=10)
62
- n.times.map {self.rand}
63
- end
64
- alias :to_a :array_of_random_values
65
-
66
- def vector_of_random_values(n=10)
67
- GSL::Vector.alloc(array_of_random_values(n))
68
- end
69
- alias :to_v :vector_of_random_values
70
-
71
- protected
72
-
73
- def is_bounded?(value)
74
- return true unless hard_lower_bound or hard_upper_bound
75
- if hard_lower_bound and hard_upper_bound
76
- value >= hard_lower_bound and value <= hard_upper_bound
77
- elsif hard_lower_bound
78
- value >= hard_lower_bound
79
- elsif hard_upper_bound
80
- value <= hard_upper_bound
81
- end
82
- end
83
-
84
- # Uses the distribution system, but doesn't use a vector to determine the sd, mean, etc.
85
- # So keeping this part in-house.
86
- def get_rand
87
- distribution.rand(sd) + mean
88
- end
89
-
90
- end
91
-
92
- end
93
-
94
- if __FILE__ == $0
95
- include Fathom
96
- # TODO: Is there anything you want to do to run this file on its own?
97
- # PlausibleRange.new
98
- end
@@ -1,59 +0,0 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), '..', 'fathom'))
2
- class Fathom::Simulation
3
-
4
- class << self
5
-
6
- # Expects a symbol for the callback to define on the simulation.
7
- def define_callback_accessor(callback, obj)
8
- call_method = callback.to_s.scan(/^on_(\w+)/).flatten.compact.first
9
- raise ArgumentError, "Callback doesn't appear to be a callback: #{callback}" unless call_method
10
- return true if self.respond_to?(call_method)
11
- define_method(call_method) do
12
- callbacks[callback].each do |agent|
13
- agent.send(callback, obj)
14
- end
15
- end
16
-
17
- agent_lookup_method = "agents_using_#{call_method}".to_sym
18
- return true if self.respond_to?(agent_lookup_method)
19
- define_method(agent_lookup_method) do
20
- callbacks[callback]
21
- end
22
-
23
- end
24
- end
25
-
26
- attr_reader :agents
27
-
28
- def initialize(*agents)
29
- @agents = agents
30
- assert_callbacks
31
- end
32
-
33
- def callbacks
34
- @callbacks ||= {}
35
- end
36
-
37
- protected
38
- def assert_callbacks
39
- self.agents.each do |agent|
40
- assert_agent(agent)
41
- end
42
- end
43
-
44
- def assert_agent(agent)
45
- return false unless agent.respond_to?(:callbacks)
46
- agent.callbacks.each do |callback|
47
- callback_sym = callback.to_sym
48
- self.callbacks[callback_sym] ||= []
49
- self.callbacks[callback_sym] << agent
50
- self.class.define_callback_accessor(callback_sym, self)
51
- end
52
- end
53
- end
54
-
55
- if __FILE__ == $0
56
- include Fathom
57
- # TODO: Is there anything you want to do to run this file on its own?
58
- # Simulation.new
59
- end
@@ -1,25 +0,0 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'fathom'))
2
- module Fathom
3
- module TickMethods
4
- def initialize(*agents)
5
- super(*agents)
6
- end
7
-
8
- attr_reader :ticks_designed, :ticks_executed
9
-
10
- def process(n)
11
- @ticks_designed = n
12
- @ticks_executed = 0
13
- n.times do
14
- self.tick(self)
15
- @ticks_executed += 1
16
- end
17
- end
18
- end
19
- end
20
-
21
- if __FILE__ == $0
22
- include Fathom
23
- # TODO: Is there anything you want to do to run this file on its own?
24
- # TicksSimulation.new
25
- end
@@ -1,12 +0,0 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'fathom'))
2
- module Fathom
3
- class TickSimulation < Simulation
4
- include TickMethods
5
- end
6
- end
7
-
8
- if __FILE__ == $0
9
- include Fathom
10
- # TODO: Is there anything you want to do to run this file on its own?
11
- # TickSimulator.new
12
- end