fathom 0.1.0 → 0.2.0

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