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,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