fathom 0.1.0 → 0.2.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.
data/.gitignore CHANGED
@@ -3,3 +3,4 @@
3
3
  coverage
4
4
  rdoc
5
5
  pkg
6
+ *.gemspec
data/README.md CHANGED
@@ -26,7 +26,8 @@ Usage
26
26
  =====
27
27
 
28
28
  Enrico Fermi [said](http://www.lucidcafe.com/library/95sep/fermi.html):
29
- There are two possible outcomes: if the result confirms the hypothesis, then you've made a measurement. If the result is contrary to the hypothesis, then you've made a discovery.
29
+ There are two possible outcomes: if the result confirms the hypothesis, then you've made a measurement.
30
+ If the result is contrary to the hypothesis, then you've made a discovery.
30
31
 
31
32
  To put together a hypothesis, we gather what we know about our problem:
32
33
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.2.0
@@ -7,23 +7,9 @@ $:.unshift(File.dirname(__FILE__))
7
7
  $:.unshift(File.expand_path(File.join(File.dirname(__FILE__), 'fathom')))
8
8
 
9
9
  require "gsl"
10
- require 'ostruct'
11
10
  require 'options_hash'
12
11
 
13
- # Fix a few bugs in OpenStruct
14
- class OpenStruct
15
- def table
16
- @table
17
- end
18
-
19
- def values
20
- @table.values
21
- end
22
-
23
- def keys
24
- @table.keys
25
- end
26
- end
12
+ require 'ext/open_struct'
27
13
 
28
14
  module Fathom
29
15
  lib = File.expand_path(File.dirname(__FILE__))
@@ -55,10 +41,19 @@ module Fathom
55
41
  autoload :SQLiteImport, 'import/sqlite_import'
56
42
 
57
43
  autoload :NodeUtilities, 'node_utilities'
44
+
45
+ autoload :Simulation, 'simulation'
46
+ autoload :TickMethods, 'simulation/tick_methods'
47
+ autoload :TickSimulation, 'simulation/tick_simulation'
48
+
49
+ autoload :Agent, 'agent'
50
+ autoload :Properties, 'agent/properties'
51
+ autoload :AgentCluster, 'agent/agent_cluster'
58
52
 
59
53
  def knowledge_base
60
54
  @knowledge_base ||= KnowledgeBase.new
61
55
  end
56
+ alias :kb :knowledge_base
62
57
  end
63
58
 
64
59
  # Temporary
@@ -0,0 +1,49 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'fathom'))
2
+ class Fathom::Agent
3
+
4
+ # =================
5
+ # = Class Methods =
6
+ # =================
7
+ class << self
8
+ def define_node_accessor(name, node)
9
+ method_name = ("node_for_" + name.to_s.downcase.gsub(/\s+/, '_')).to_sym
10
+ define_method(method_name) do
11
+ node
12
+ end
13
+ end
14
+ end
15
+
16
+ include Properties
17
+
18
+ def initialize(opts={})
19
+ self.class.define_property_states
20
+ assert_node_accessors(opts)
21
+ end
22
+
23
+ def states
24
+ @states ||= self.class.properties.inject({}) do |h, state_method_name|
25
+ h[state_method_name] = nil
26
+ h
27
+ end
28
+ end
29
+
30
+ def callbacks
31
+ @callbacks ||= (self.methods - Object.methods).grep(/^on_(\w+)/)
32
+ end
33
+
34
+ protected
35
+ def assert_node_accessors(nodes)
36
+ nodes.each do |name, node|
37
+ next unless self.class.properties.include?(name)
38
+ states[name] = node.respond_to?(:rand) ? node.rand : node
39
+ self.class.define_node_accessor(name, node)
40
+ end
41
+ end
42
+
43
+ end
44
+
45
+ if __FILE__ == $0
46
+ include Fathom
47
+ # TODO: Is there anything you want to do to run this file on its own?
48
+ # Agent.new
49
+ end
@@ -0,0 +1,23 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'fathom'))
2
+
3
+ =begin
4
+ This class is designed to hold a cluster of agents in memory. It runs the simulation locally and
5
+ speaks to other clusters via EventMachine. In this way, we don't need a Ruby runtime/thread/fiber
6
+ for each agent, just one per dozen/hundred/thousand agents, depending on what balances the
7
+ simulation.
8
+ =end
9
+ class Fathom::AgentCluster
10
+
11
+ attr_reader :agents
12
+
13
+ def initialize(*agents)
14
+ @agents = agents
15
+ end
16
+
17
+ end
18
+
19
+ if __FILE__ == $0
20
+ include Fathom
21
+ # TODO: Is there anything you want to do to run this file on its own?
22
+ # AgentCluster.new
23
+ end
@@ -0,0 +1,48 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'fathom'))
2
+ module Fathom
3
+ module Properties
4
+
5
+ def self.included(base)
6
+ base.send(:extend, ClassMethods)
7
+ end
8
+
9
+ module ClassMethods
10
+
11
+ def properties
12
+ @properties ||= []
13
+ end
14
+
15
+ def property(name, opts={})
16
+ self.properties << name_sym(name)
17
+ end
18
+
19
+ def define_property_states
20
+ return true if @property_states_defined
21
+ self.properties.each do |state_method_name|
22
+ unless self.instance_methods.include?(state_method_name.to_s)
23
+ define_method(state_method_name) do
24
+ states[state_method_name]
25
+ end
26
+ end
27
+
28
+ state_method_writer = "#{state_method_name}=".to_sym
29
+ unless self.instance_methods.include?(state_method_writer.to_s)
30
+ define_method(state_method_writer) do |value|
31
+ states[state_method_name] = value
32
+ end
33
+ end
34
+ end
35
+
36
+ @property_states_defined = true
37
+ end
38
+
39
+ protected
40
+ def name_sym(name)
41
+ name.to_s.downcase.gsub(/\s+/, '_').to_sym
42
+ end
43
+
44
+ end
45
+ end
46
+ end
47
+
48
+
@@ -0,0 +1 @@
1
+ FasterCSV::HeaderConverters[:strip] = lambda{|h| h.strip}
@@ -0,0 +1,17 @@
1
+ require 'ostruct'
2
+
3
+ # Fix a few bugs in OpenStruct
4
+ class OpenStruct
5
+ def table
6
+ @table
7
+ end
8
+
9
+ def values
10
+ @table.values
11
+ end
12
+
13
+ def keys
14
+ @table.keys
15
+ end
16
+ end
17
+
@@ -35,6 +35,13 @@ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'fathom'))
35
35
  =end
36
36
  class Fathom::Import
37
37
 
38
+ class << self
39
+ def import(opts={})
40
+ importer = new(opts)
41
+ importer.import
42
+ end
43
+ end
44
+
38
45
  attr_reader :content, :options
39
46
 
40
47
  def initialize(opts={})
@@ -47,7 +54,8 @@ class Fathom::Import
47
54
  import_methods.each do |method|
48
55
  klass, initialization_data = self.send(method.to_sym)
49
56
  initialization_data.each do |values|
50
- results << extract_nodes(klass, values)
57
+ node = extract_nodes(klass, values)
58
+ results << node if node
51
59
  end
52
60
  end
53
61
  results
@@ -55,10 +63,15 @@ class Fathom::Import
55
63
 
56
64
  protected
57
65
 
66
+ # Just blankly try to initiate a node. If it fails, silently fail for now.
58
67
  def extract_nodes(klass, values)
59
- node = klass.new(values)
60
- Fathom.knowledge_base[node.name] = node
61
- node
68
+ begin
69
+ node = klass.new(values)
70
+ Fathom.knowledge_base[node.name] = node
71
+ node
72
+ rescue
73
+ nil
74
+ end
62
75
  end
63
76
 
64
77
  def import_methods
@@ -4,6 +4,7 @@ require 'open-uri'
4
4
 
5
5
  # TODO: Work this out with Ruby 1.9. We don't need to load this for all Rubies.
6
6
  require 'fastercsv'
7
+ require 'ext/faster_csv'
7
8
 
8
9
  module Fathom
9
10
  class CSVImport < Import
@@ -23,7 +24,7 @@ module Fathom
23
24
  def parse_options
24
25
  return @parse_options if @parse_options
25
26
  @parse_options = @options[:parse_options]
26
- @parse_options ||= {:converters => [:all], :headers => true, :skip_blanks => true}
27
+ @parse_options ||= {:converters => [:all], :headers => true, :skip_blanks => true, :header_converters => [:strip, :symbol]}
27
28
  @parse_options
28
29
  end
29
30
 
@@ -1,5 +1,6 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'fathom'))
2
2
  require 'open-uri'
3
+ require 'yaml'
3
4
 
4
5
  class Fathom::YAMLImport < Import
5
6
  def import_plausible_ranges
@@ -31,7 +32,8 @@ class Fathom::YAMLImport < Import
31
32
  name, value = array.first, array.last
32
33
  if value.is_a?(Hash)
33
34
  value = OptionsHash.new(value)
34
- list << value.merge(:name => name) if value[:min] and value[:max]
35
+ # list << value.merge(:name => name) if value[:min] and value[:max]
36
+ list << value.merge(:name => name)
35
37
  end
36
38
  list
37
39
  end
@@ -1,17 +1,29 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), '..', 'fathom'))
2
2
  class Fathom::KnowledgeBase
3
3
 
4
+ attr_reader :data_store
5
+
4
6
  def initialize(opts={})
5
7
  opts = OptionsHash.new(opts)
6
- @data_store = {}
8
+ @data_store = OpenStruct.new
7
9
  end
8
10
 
9
11
  def []=(key, value)
10
- @data_store[key] = value
12
+ @data_store.table[key] = value
11
13
  end
12
14
 
13
15
  def [](key)
14
- @data_store[key]
16
+ @data_store.table[key]
17
+ end
18
+
19
+ # This is temporary, but useful for now. After we have the persisted KnowledgeBase,
20
+ # we'll create explicit accessor methods or a find syntax.
21
+ def method_missing(sym, *args, &block)
22
+ if @data_store.table.keys.include?(sym)
23
+ @data_store.send(sym)
24
+ else
25
+ super
26
+ end
15
27
  end
16
28
 
17
29
  end
@@ -52,7 +52,11 @@ module Fathom
52
52
 
53
53
  # Not using specific distributions yet
54
54
  def rand
55
- rng.gaussian(std) + midpoint
55
+ value = get_rand
56
+ until is_bounded?(value) do
57
+ value= get_rand
58
+ end
59
+ value
56
60
  end
57
61
 
58
62
  def array_of_random_values(n=10)
@@ -66,6 +70,22 @@ module Fathom
66
70
  alias :to_v :vector_of_random_values
67
71
 
68
72
  protected
73
+
74
+ def is_bounded?(value)
75
+ return true unless hard_lower_bound or hard_upper_bound
76
+ if hard_lower_bound and hard_upper_bound
77
+ value >= hard_lower_bound and value <= hard_upper_bound
78
+ elsif hard_lower_bound
79
+ value >= hard_lower_bound
80
+ elsif hard_upper_bound
81
+ value <= hard_upper_bound
82
+ end
83
+ end
84
+
85
+ def get_rand
86
+ rng.gaussian(std) + midpoint
87
+ end
88
+
69
89
  def rng
70
90
  @rng ||= GSL::Rng.alloc
71
91
  end
@@ -0,0 +1,59 @@
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
@@ -0,0 +1,25 @@
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
@@ -0,0 +1,12 @@
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
@@ -0,0 +1,17 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ include Fathom
4
+
5
+ describe AgentCluster do
6
+
7
+ before do
8
+ @agent = double()
9
+ @agents = [@agent]
10
+ end
11
+
12
+ it "should initialize with a set of agents" do
13
+ @ac = AgentCluster.new @agent
14
+ @ac.agents.should eql(@agents)
15
+ end
16
+
17
+ end
@@ -0,0 +1,51 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ include Fathom
4
+
5
+ describe Agent do
6
+
7
+ before do
8
+ @pr1 = PlausibleRange.new(:min => 1, :max => 2)
9
+ @pr2 = PlausibleRange.new(:min => 10, :max => 11)
10
+ @da = DemoAgent.new(:field1 => @pr1, :field2 => @pr2)
11
+ end
12
+
13
+ it "should be have a list of properties" do
14
+ DemoAgent.properties.should eql([:field1, :field2])
15
+ end
16
+
17
+ it "should be able to set a seed node for each property defined in the class" do
18
+ @da.node_for_field1.should eql(@pr1)
19
+ @da.node_for_field2.should eql(@pr2)
20
+ end
21
+
22
+ it "should not set a seed node for a node that doesn't have a property" do
23
+ da = DemoAgent.new(:field1 => @pr1, :field2 => @pr2, :field3 => :should_not_be_found)
24
+ da.should_not be_respond_to(:node_for_field3)
25
+ end
26
+
27
+ it "should have a state accessor for each property" do
28
+ @da.should be_respond_to(:field1)
29
+ @da.should be_respond_to(:field1=)
30
+ @da.should be_respond_to(:field2)
31
+ @da.should be_respond_to(:field2=)
32
+ end
33
+
34
+ it "should set the initial state of each property from the seed node, if defined" do
35
+ @pr1.should_receive(:rand).and_return(1.5)
36
+ @pr2.should_not_receive(:rand)
37
+ @da = DemoAgent.new(:field1 => @pr1)
38
+ @da.field1.should eql(1.5)
39
+ @da.field2.should be_nil
40
+ end
41
+
42
+ it "should be able to send a hard parameter and save it in a property" do
43
+ @da = DemoAgent.new(:field1 => 2)
44
+ @da.field1.should eql(2)
45
+ end
46
+
47
+ it "should expose the callbacks, those methods starting with on_" do
48
+ @da.callbacks.should eql(["on_tick"])
49
+ end
50
+
51
+ end
@@ -33,4 +33,14 @@ describe CSVImport do
33
33
  @result[2].values.should eql([3,6,9])
34
34
  end
35
35
 
36
+ it "should store the imported values in the knowledge base" do
37
+ Fathom.knowledge_base[:this].should be_a(DataNode)
38
+ Fathom.kb[:this].values.should eql([1,4,7])
39
+ end
40
+
41
+ it "should import from the class level" do
42
+ CSVImport.import(@opts)
43
+ Fathom.knowledge_base[:this].should be_a(DataNode)
44
+ Fathom.kb[:this].values.should eql([1,4,7])
45
+ end
36
46
  end
@@ -37,4 +37,15 @@ describe YAMLImport do
37
37
  data_node.values.should eql([10,20,30])
38
38
  end
39
39
 
40
+ it "should store the imported values in the knowledge base" do
41
+ Fathom.knowledge_base['CO2 Emissions'].should be_a(PlausibleRange)
42
+ Fathom.kb['CO2 Emissions'].min.should eql(1_000_000)
43
+ end
44
+
45
+ it "should import from the class level" do
46
+ YAMLImport.import(@opts)
47
+ Fathom.knowledge_base['CO2 Emissions'].should be_a(PlausibleRange)
48
+ Fathom.kb['CO2 Emissions'].min.should eql(1_000_000)
49
+ end
50
+
40
51
  end
@@ -11,7 +11,7 @@ describe Import do
11
11
  @values = [1,2,3,4,5]
12
12
  end
13
13
 
14
- it "should initialize with a optional content" do
14
+ it "should initialize with optional content" do
15
15
  @i.content.should eql(@content)
16
16
  end
17
17
 
@@ -19,4 +19,8 @@ describe Import do
19
19
  @i.options.should eql(@options)
20
20
  end
21
21
 
22
+ it "should have a class-level import method" do
23
+ Import.should be_respond_to(:import)
24
+ end
25
+
22
26
  end
@@ -127,4 +127,26 @@ describe PlausibleRange do
127
127
  pr.name_sym.should eql(:demo_node)
128
128
  end
129
129
 
130
+ it "should not exceed the lower bound if it is set", :slow => true do
131
+ pr = PlausibleRange.new(:max => 100, :hard_lower_bound => 0)
132
+ 1_000.times do
133
+ (pr.rand >= 0).should eql(true)
134
+ end
135
+ end
136
+
137
+ it "should not exceed the upper bound if it is set", :slow => true do
138
+ pr = PlausibleRange.new(:min => 0, :hard_upper_bound => 100)
139
+ 1_000.times do
140
+ (pr.rand <= 100).should eql(true)
141
+ end
142
+ end
143
+
144
+ it "should not exceed the lower bound or upper bound if both are set", :slow => true do
145
+ pr = PlausibleRange.new(:hard_upper_bound => 100, :hard_lower_bound => 0)
146
+ 1_000.times do
147
+ r = pr.rand
148
+ (r >= 0 and r <= 100).should eql(true)
149
+ end
150
+ end
151
+
130
152
  end
@@ -0,0 +1,32 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ include Fathom
4
+
5
+ describe TickSimulation do
6
+
7
+ before do
8
+ @da = DemoAgent.new
9
+ end
10
+
11
+ it "should process with n ticks" do
12
+ @da.should_receive(:on_tick).exactly(3).times.and_return(true)
13
+ s = TickSimulation.new(@da)
14
+ s.process(3)
15
+ end
16
+
17
+ it "should expose the number of ticks designed and executed after processing" do
18
+ s = TickSimulation.new(@da)
19
+ s.process(4)
20
+ s.ticks_designed.should eql(4)
21
+ s.ticks_executed.should eql(4)
22
+ end
23
+
24
+ # Any calls coming top down (from the simulator or the agent cluster), will need a standard signature to
25
+ # make things interchangeable. We use the simulator itself, which is a bit fat, but will work for the short
26
+ # term.
27
+ it "should pass the simulator on tick" do
28
+ s = TickSimulation.new(@da)
29
+ @da.should_receive(:on_tick).with(s)
30
+ s.process(1)
31
+ end
32
+ end
@@ -0,0 +1,24 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ include Fathom
4
+
5
+ describe Simulation do
6
+ before do
7
+ @da = DemoAgent.new
8
+ @s = Simulation.new(@da)
9
+ end
10
+
11
+ it "should initialize with a list of agents" do
12
+ s = Simulation.new(1,2,3)
13
+ s.agents.should eql([1,2,3])
14
+ end
15
+
16
+ it "should register agent callbacks for simpler execution" do
17
+ @da.should_receive(:on_tick).and_return(true)
18
+ @s.tick
19
+ end
20
+
21
+ it "should publish agent subscription to various callbacks to facilitate agent-to-agent communication" do
22
+ @s.agents_using_tick.should eql([@da])
23
+ end
24
+ end
@@ -5,4 +5,12 @@ describe "Fathom" do
5
5
  Fathom.included_modules.should_not be_include(GSL)
6
6
  lambda{GSL}.should_not raise_error
7
7
  end
8
+
9
+ it "should have a knowledge base" do
10
+ Fathom.knowledge_base.should be_a(KnowledgeBase)
11
+ end
12
+
13
+ it "should alias kb for knowledge_base" do
14
+ Fathom.kb.should eql(Fathom.knowledge_base)
15
+ end
8
16
  end
@@ -1,6 +1,6 @@
1
1
  CO2 Emissions:
2
- min: 1_000_000
3
- max: 1_000_000_000
2
+ min: 1000000
3
+ max: 1000000000
4
4
 
5
5
  Invalid Hash:
6
6
  different: signature
@@ -0,0 +1,8 @@
1
+ class DemoAgent < Agent
2
+ property :field1
3
+ property :field2
4
+
5
+ def on_tick(simulation)
6
+ end
7
+
8
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fathom
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 23
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 1
8
+ - 2
9
9
  - 0
10
- version: 0.1.0
10
+ version: 0.2.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - David
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-11-05 00:00:00 -06:00
18
+ date: 2010-11-07 00:00:00 -06:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -53,7 +53,11 @@ files:
53
53
  - Rakefile
54
54
  - VERSION
55
55
  - autotest/discover.rb
56
+ - fathom.gemspec
56
57
  - lib/fathom.rb
58
+ - lib/fathom/agent.rb
59
+ - lib/fathom/agent/agent_cluster.rb
60
+ - lib/fathom/agent/properties.rb
57
61
  - lib/fathom/archive/conditional_probability_matrix.rb
58
62
  - lib/fathom/archive/n2.rb
59
63
  - lib/fathom/archive/n3.rb
@@ -65,6 +69,8 @@ files:
65
69
  - lib/fathom/combined_plausibilities.rb
66
70
  - lib/fathom/concept.rb
67
71
  - lib/fathom/data_node.rb
72
+ - lib/fathom/ext/faster_csv.rb
73
+ - lib/fathom/ext/open_struct.rb
68
74
  - lib/fathom/import.rb
69
75
  - lib/fathom/import/csv_import.rb
70
76
  - lib/fathom/import/yaml_import.rb
@@ -73,10 +79,15 @@ files:
73
79
  - lib/fathom/monte_carlo_set.rb
74
80
  - lib/fathom/node_utilities.rb
75
81
  - lib/fathom/plausible_range.rb
82
+ - lib/fathom/simulation.rb
83
+ - lib/fathom/simulation/tick_methods.rb
84
+ - lib/fathom/simulation/tick_simulation.rb
76
85
  - lib/fathom/value_aggregator.rb
77
86
  - lib/fathom/value_description.rb
78
87
  - lib/fathom/value_multiplier.rb
79
88
  - lib/options_hash.rb
89
+ - spec/fathom/agent/agent_cluster_spec.rb
90
+ - spec/fathom/agent_spec.rb
80
91
  - spec/fathom/data_node_spec.rb
81
92
  - spec/fathom/import/csv_import_spec.rb
82
93
  - spec/fathom/import/yaml_import_spec.rb
@@ -84,10 +95,13 @@ files:
84
95
  - spec/fathom/knowledge_base_spec.rb
85
96
  - spec/fathom/monte_carlo_set_spec.rb
86
97
  - spec/fathom/plausible_range_spec.rb
98
+ - spec/fathom/simulation/tick_simulation_spec.rb
99
+ - spec/fathom/simulation_spec.rb
87
100
  - spec/fathom/value_description_spec.rb
88
101
  - spec/fathom_spec.rb
89
102
  - spec/spec_helper.rb
90
103
  - spec/support/demo.yml
104
+ - spec/support/demo_agent.rb
91
105
  has_rdoc: true
92
106
  homepage: http://github.com/davidrichards/fathom
93
107
  licenses: []
@@ -123,6 +137,8 @@ signing_key:
123
137
  specification_version: 3
124
138
  summary: Decision Support in Ruby
125
139
  test_files:
140
+ - spec/fathom/agent/agent_cluster_spec.rb
141
+ - spec/fathom/agent_spec.rb
126
142
  - spec/fathom/data_node_spec.rb
127
143
  - spec/fathom/import/csv_import_spec.rb
128
144
  - spec/fathom/import/yaml_import_spec.rb
@@ -130,6 +146,9 @@ test_files:
130
146
  - spec/fathom/knowledge_base_spec.rb
131
147
  - spec/fathom/monte_carlo_set_spec.rb
132
148
  - spec/fathom/plausible_range_spec.rb
149
+ - spec/fathom/simulation/tick_simulation_spec.rb
150
+ - spec/fathom/simulation_spec.rb
133
151
  - spec/fathom/value_description_spec.rb
134
152
  - spec/fathom_spec.rb
135
153
  - spec/spec_helper.rb
154
+ - spec/support/demo_agent.rb