optimal-control 0.0.2

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.
@@ -0,0 +1,4 @@
1
+
2
+ v0.0.2 Issue with resource pathing on version 0.0.1 resolved
3
+
4
+ v0.0.1 initial format
@@ -0,0 +1,11 @@
1
+ CHANGELOG
2
+ Manifest
3
+ README
4
+ Rakefile
5
+ bin/optimalcontrol
6
+ lib/cgl/evaluate.rb
7
+ lib/cgl/neighbors.rb
8
+ lib/cgl/runner.rb
9
+ test/test_evaluate.rb
10
+ test/test_neighbors.rb
11
+ test/test_runner.rb
data/README ADDED
@@ -0,0 +1,17 @@
1
+ Optimal Control for Conway's game of Life - 0.0.1
2
+ Franziska Hinkelmann
3
+ fhinkel@vt.edu
4
+
5
+
6
+ This gem will generate an optimal controller for Conway's game of Life on a n
7
+ x n grid with periodic boundary conditions. The control objective is to have
8
+ the left upper corner dead after m iterations, the control that can be applied
9
+ is to kill the cell one to the right of it.
10
+
11
+ Cost for control is 1 cost unit, independent of the iteration step it is
12
+ applied to. Every initial state to which control should be applied is
13
+ reported, including the iteration steps at which control should be applied.
14
+
15
+ Unit tests are in test/
16
+
17
+
@@ -0,0 +1,36 @@
1
+ require 'rake/gempackagetask'
2
+ require 'echoe'
3
+
4
+ #spec = Gem::Specification.new do |s|
5
+ # s.name = "optimal-control"
6
+ # s.summary = "Simulate Conway's game of Life on a small grid with periodic
7
+ # boundary conditions and find the optimal controller for the specified
8
+ # control objective and control options"
9
+ # s.description= File.read(File.join(File.dirname(__FILE__), 'README'))
10
+ # s.author = "Franziska Hinkelmann"
11
+ # s.email = "fhinkel@vt.edu"
12
+ # s.version = "0.0.2"
13
+ # s.platform = Gem::Platform::RUBY
14
+ # s.required_ruby_version = '>=1.8.6'
15
+ # s.files = Dir['**/**']
16
+ # s.executables = [ 'optimalcontrol' ]
17
+ # s.test_files = Dir["test/test*.rb"]
18
+ # s.has_rdoc = false
19
+ #end
20
+ #Rake::GemPackageTask.new(spec).define
21
+
22
+ spec = Echoe.new("optimal-control") do |s|
23
+ s.summary = "Simulate Conway's game of Life on a small grid with periodic
24
+ boundary conditions and find the optimal controller for the specified
25
+ control objective and control options"
26
+ #s.description= File.read(File.join(File.dirname(__FILE__), 'README'))
27
+ s.author = "Franziska Hinkelmann"
28
+ s.email = "fhinkel@vt.edu"
29
+ s.url = "http://rubyforge.org/projects/optimal-control/"
30
+ s.platform = Gem::Platform::RUBY
31
+ #s.required_ruby_version = '>=1.8.6'
32
+ #s.files = Dir['**/**']
33
+ #s.executables = [ 'optimalcontrol' ]
34
+ #s.test_files = Dir["test/test*.rb"]
35
+ #s.has_rdoc = false
36
+ end
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/env ruby
2
+ require File.dirname(__FILE__) + '/../lib/cgl/runner'
3
+
4
+ # Optimal Control for a 4by4 Conways game of life, control objective is
5
+ # defined in the assign_final_cost function
6
+ # assume control is 1 unit cost per cell, the central 4 cells can be
7
+ # independently controlled
8
+
9
+ if /-h/ =~ ARGV.to_s
10
+ puts
11
+ puts "Optimal Control for Conway's Game of Life"
12
+ puts
13
+ puts "Usage: bin/optimalconrol Iterations Height Width"
14
+ puts "Default values are 5 for the number of steps to iterate, and 2 as\
15
+ grid height and width of the grid."
16
+ puts
17
+ exit
18
+ end
19
+
20
+ Steps = ARGV[0].to_i - 1 || 4 # Steps + 1 iterations
21
+
22
+ unless 0 <= Steps
23
+ puts "The first argument, the number of iterations, must be an integer at least 1"
24
+ exit
25
+ end
26
+
27
+ Max_cost = (Steps+1)*4 + 1 # make states that are not admissible more expensive than
28
+ # applying control before all #Steps iterations
29
+
30
+ Grid_height = ARGV[1].to_i || 2
31
+ unless 0 < Grid_height && Grid_height < 5
32
+ puts "The second argument, height of the grid, must be an integer between 1 and 5"
33
+ exit
34
+ end
35
+ Grid_width = ARGV[2].to_i || Grid_height # if no hight is given, use a square grid
36
+ unless 0 < Grid_width && Grid_width < 5
37
+ puts "The third argument, width of the grid, must be an integer between 1 and 5"
38
+ exit
39
+ end
40
+
41
+
42
+ runner = Cgl::Runner.new(Steps, Max_cost, Grid_height, Grid_width)
43
+
44
+ # result = [cost_vector[0], control[0]]
45
+ result = runner.run
46
+
47
+ n_agents = Grid_height * Grid_width
48
+ cost_vector = result[0]
49
+ control = result[1]
50
+
51
+ # print all states that can lead to a valid final state
52
+ # TODO print control input to reach final state
53
+ for i in 0..2**n_agents-1 do
54
+ if (cost_vector[i]>0)
55
+ puts "%0#{n_agents}d" % i.to_s(2) + ": cost = #{cost_vector[i]}, control applied at timeSteps \"#{control[i]}\""
56
+ end
57
+ end
58
+
@@ -0,0 +1,26 @@
1
+ module Cgl
2
+ class Evaluate
3
+ # given an array of length 9, where the first entry is the agent to
4
+ # update, return the agents updated value
5
+ def self.evaluate( neighbors )
6
+ agent = neighbors.shift.to_i
7
+ number_of_alive_neighbors = neighbors.inject(0){|sum,item| sum.to_i + item.to_i }
8
+ # assume the very first column is the agent we're computing the next state
9
+ # for
10
+ if (number_of_alive_neighbors < 2)
11
+ f = 0
12
+ elsif (number_of_alive_neighbors == 2)
13
+ if (agent==1)
14
+ f = 1
15
+ else
16
+ f = 0
17
+ end
18
+ elsif (number_of_alive_neighbors == 3)
19
+ f = 1
20
+ else # number_of_alive_neighbors > 3
21
+ f = 0
22
+ end
23
+ f
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ module Cgl
2
+ class Neighbors
3
+ # given the index of an agent and the full grid, return an array with the
4
+ # values of the 8 neighboring agents
5
+ # assume periodic boundary conditions (wrap)
6
+ # all indexing is 0 based, so a 3 x 4 grid has these indexes:
7
+ # 0 1 2 3
8
+ # 4 5 6 7
9
+ # 8 9 10 11
10
+ #
11
+ def self.neighbors(agent, all_agents, height, width = height)
12
+ neighbors = Array.new
13
+ row = agent/width
14
+ column = agent%width
15
+ neighbors.push all_agents[(row*width)+(column+1)%width]
16
+ neighbors.push all_agents[((row+1)%height)*width+(column+1)%width]
17
+ neighbors.push all_agents[((row+1)%height)*width+(column)]
18
+ neighbors.push all_agents[((row+1)%height)*width+(column-1)%width]
19
+ neighbors.push all_agents[row*width+(column-1)%width]
20
+ neighbors.push all_agents[(row-1)*width+(column-1)%width]
21
+ neighbors.push all_agents[(row-1)*width+(column)]
22
+ neighbors.push all_agents[(row-1)*width+(column+1)%width]
23
+ neighbors
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,90 @@
1
+ require File.dirname(__FILE__) + '/evaluate'
2
+ require File.dirname(__FILE__) + '/neighbors'
3
+
4
+ module Cgl
5
+ class Runner
6
+ attr_reader :steps
7
+ attr_reader :max_cost
8
+ attr_reader :grid_height
9
+ attr_reader :grid_width
10
+ attr_reader :n_agents
11
+ def initialize( steps, max_cost, grid_height, grid_width = grid_height )
12
+ @steps = steps
13
+ @max_cost = max_cost
14
+ @grid_height = grid_height
15
+ @grid_width = grid_width
16
+ @n_agents = grid_height * grid_width
17
+ end
18
+
19
+ def run
20
+ cost_vector = Array.new(@steps+2) # cost_vector[i][state]cost of getting from state to admissible state in
21
+ # @steps+2-i time@steps
22
+
23
+ # control[j][i] has a sequence for applying control to state i
24
+ control = Array.new(@steps+2) # need an extra vector of empty strings, so we
25
+ #can later concatenate without worrying about being at the last entry
26
+ for i in 0..@steps+1 do
27
+ cost_vector[i] = Array.new(2**@n_agents)
28
+ control[i] = Array.new(2**@n_agents, "")
29
+ end
30
+
31
+ for i in 0..2**@n_agents-1 do
32
+ cost_vector[@steps+1][i] = assign_final_cost(i)
33
+ end
34
+
35
+ for j in 0..@steps do
36
+ puts @steps - j
37
+ for i in 0..2**@n_agents-1 do
38
+ i_as_array = ("%0#{@n_agents}d" % i.to_s(2)).split(//)
39
+
40
+ # calculate cost without control
41
+ output = iterate i_as_array
42
+ state = output.to_s.to_i(2)
43
+ cost_without_control = cost_vector[@steps-j+1][state]
44
+
45
+ # calculate cost with control and take min
46
+ # TODO pass agent to kill as arg
47
+ # control: kill agent 2
48
+ i_as_array[1] = "0"
49
+ output = iterate i_as_array
50
+ state_with_control = output.to_s.to_i(2)
51
+ cost_for_control = 1
52
+ cost_with_control = cost_vector[@steps-j+1][state_with_control] + cost_for_control
53
+
54
+ # take min and record if control was applied
55
+ if (cost_without_control < cost_with_control)
56
+ cost_vector[@steps-j][i] = cost_without_control
57
+ control[@steps-j][i] = control[@steps-j+1][state]
58
+ else
59
+ cost_vector[@steps-j][i] = cost_with_control
60
+ control[@steps-j][i] = "#{@steps-j+1}" + control[@steps-j+1][state_with_control]
61
+ end
62
+ end
63
+ end
64
+
65
+ [cost_vector[0], control[0]]
66
+ end
67
+
68
+ private
69
+ def assign_final_cost( state )
70
+ # valid if agent 1 is dead
71
+ if ( state < 2**(@n_agents - 1) )
72
+ cost = 0
73
+ else
74
+ cost = @max_cost
75
+ end
76
+ cost
77
+ end
78
+
79
+ def iterate( i_as_array )
80
+ output = Array.new(@n_agents)
81
+ for k in 0..@n_agents-1 do # update all N_agents states
82
+ input_data = Cgl::Neighbors.neighbors(k, i_as_array, @grid_height,
83
+ @grid_width)
84
+ output[k] = Cgl::Evaluate.evaluate([i_as_array[k]] + input_data)
85
+ end
86
+ output
87
+ end
88
+ end
89
+ end
90
+
@@ -0,0 +1,35 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{optimal-control}
5
+ s.version = "0.0.2"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Franziska Hinkelmann"]
9
+ s.date = %q{2010-01-01}
10
+ s.default_executable = %q{optimalcontrol}
11
+ s.description = %q{Simulate Conway's game of Life on a small grid with periodic
12
+ boundary conditions and find the optimal controller for the specified
13
+ control objective and control options}
14
+ s.email = %q{fhinkel@vt.edu}
15
+ s.executables = ["optimalcontrol"]
16
+ s.extra_rdoc_files = ["CHANGELOG", "README", "bin/optimalcontrol", "lib/cgl/evaluate.rb", "lib/cgl/neighbors.rb", "lib/cgl/runner.rb"]
17
+ s.files = ["CHANGELOG", "Manifest", "README", "Rakefile", "bin/optimalcontrol", "lib/cgl/evaluate.rb", "lib/cgl/neighbors.rb", "lib/cgl/runner.rb", "test/test_evaluate.rb", "test/test_neighbors.rb", "test/test_runner.rb", "optimal-control.gemspec"]
18
+ s.homepage = %q{http://rubyforge.org/projects/optimal-control/}
19
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Optimal-control", "--main", "README"]
20
+ s.require_paths = ["lib"]
21
+ s.rubyforge_project = %q{optimal-control}
22
+ s.rubygems_version = %q{1.3.5}
23
+ s.summary = %q{Simulate Conway's game of Life on a small grid with periodic boundary conditions and find the optimal controller for the specified control objective and control options}
24
+ s.test_files = ["test/test_evaluate.rb", "test/test_neighbors.rb", "test/test_runner.rb"]
25
+
26
+ if s.respond_to? :specification_version then
27
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
28
+ s.specification_version = 3
29
+
30
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
31
+ else
32
+ end
33
+ else
34
+ end
35
+ end
@@ -0,0 +1,48 @@
1
+ require 'test/unit'
2
+ require 'rubygems'
3
+ require 'shoulda'
4
+
5
+ require 'lib/cgl/evaluate'
6
+
7
+ class TestEvaluate < Test::Unit::TestCase
8
+ context "alive agent" do
9
+ should "die as if caused by underpopulation" do
10
+ agent = Cgl::Evaluate.evaluate( ["1", "1"] )
11
+ assert_equal agent, 0
12
+ agent = Cgl::Evaluate.evaluate( ["1"] )
13
+ assert_equal agent, 0
14
+ end
15
+ should "die as if by overcrowding " do
16
+ agent = Cgl::Evaluate.evaluate( ["1", "1", "1", "1", "1"] )
17
+ assert_equal agent, 0
18
+ end
19
+ should "life on with 2 or 3 neighbors" do
20
+ agent = Cgl::Evaluate.evaluate( ["1", "1", "1"] )
21
+ assert_equal agent, 1
22
+ agent = Cgl::Evaluate.evaluate( ["1", "0", "0", "0", "1", "1"] )
23
+ assert_equal agent, 1
24
+ agent = Cgl::Evaluate.evaluate( ["1", "1", "1", "1"] )
25
+ assert_equal agent, 1
26
+ agent = Cgl::Evaluate.evaluate( ["1", "1", "0", "1", "1", "0", "0", "0",
27
+ "0"] )
28
+ assert_equal agent, 1
29
+ agent = Cgl::Evaluate.evaluate( ["1", "0", "0", "1", "1", "0", "0", "0",
30
+ "0"] )
31
+ assert_equal agent, 1
32
+ end
33
+ end
34
+ context "dead agent" do
35
+ should "become a live cell with 3 neighbors" do
36
+ agent = Cgl::Evaluate.evaluate( ["0", "1", "1", "1"] )
37
+ assert_equal agent, 1
38
+ agent = Cgl::Evaluate.evaluate( ["0", "0", "0", "0","1", "1", "1","0", "0"] )
39
+ assert_equal agent, 1
40
+ agent = Cgl::Evaluate.evaluate( ["0", "1", "0", "0","1", "0", "1"] )
41
+ assert_equal agent, 1
42
+ agent = Cgl::Evaluate.evaluate( ["1", "1", "0", "1", "1", "0","0", "0",
43
+ "0"] )
44
+ assert_equal agent, 1
45
+ end
46
+ end
47
+ end
48
+
@@ -0,0 +1,43 @@
1
+ require 'test/unit'
2
+ require 'rubygems'
3
+ require 'shoulda'
4
+
5
+ require 'lib/cgl/neighbors'
6
+
7
+ class TestNeighbors < Test::Unit::TestCase
8
+ context "agent in a 1 by 1 grid " do
9
+ should "have all 8 neighbors the same" do
10
+ neighbors = Cgl::Neighbors.neighbors(0, ["0"], 1)
11
+ assert_equal ["0", "0", "0", "0", "0", "0", "0", "0"], neighbors
12
+ neighbors = Cgl::Neighbors.neighbors(0, ["aa"], 1)
13
+ assert_equal ["aa", "aa", "aa", "aa", "aa", "aa", "aa", "aa"], neighbors
14
+ end
15
+ end
16
+ context "agent a in a 2 by 2 grid " do
17
+ should "have all 8 neighbors bdcdbdcdb" do
18
+ neighbors = Cgl::Neighbors.neighbors(0, ["a", "b", "c", "d"], 2)
19
+ assert_equal ["b", "d", "c", "d", "b", "d", "c", "d"], neighbors
20
+ end
21
+ end
22
+ context "central agent a in a 3 by 3 grid " do
23
+ should "have all normal 8 neighbors" do
24
+ neighbors = Cgl::Neighbors.neighbors(4, ["a", "b", "c", "d", "e", "f", "g", "h", "i"], 3)
25
+ assert_equal ["f", "i", "h", "g", "d", "a", "b", "c"], neighbors
26
+ end
27
+ end
28
+ context "upper right agent a in a 2 by 3 grid " do
29
+ should "have all normal 8 neighbors" do
30
+ neighbors = Cgl::Neighbors.neighbors(0, ["a", "b", "c", "d", "e", "f"],
31
+ 2, 3)
32
+ assert_equal ["b", "e", "d", "f", "c", "f", "d", "e"], neighbors
33
+ end
34
+ end
35
+ context "lower right corner on 3 by 3 grid" do
36
+ should "have the following neighbors" do
37
+ neighbors = Cgl::Neighbors.neighbors(8, ["a", "b", "c", "d", "e", "f", "g", "h", "i"], 3)
38
+ assert_equal ["g", "a", "c", "b", "h", "e", "f", "d"], neighbors
39
+ end
40
+ end
41
+
42
+ end
43
+
@@ -0,0 +1,114 @@
1
+ require 'test/unit'
2
+ require 'rubygems'
3
+ require 'shoulda'
4
+
5
+ require 'lib/cgl/runner'
6
+
7
+ class TestRunner < Test::Unit::TestCase
8
+ context "2 by 2 grid, 1 timestep " do
9
+ should "have these intial states with max cost" do
10
+ steps = 0
11
+ max_cost = (steps+1)*1 + 1
12
+ grid_size = 2
13
+ n_agents = grid_size**2
14
+ runner = Cgl::Runner.new(steps, max_cost, grid_size)
15
+ result = runner.run
16
+ assert_equal 2, result.size
17
+ cost_vector = result[0]
18
+ control = result[1]
19
+ assert_equal 2**n_agents, cost_vector.size
20
+ assert_equal 2**n_agents, control.size
21
+ for i in 0..2**n_agents-1
22
+ unless cost_vector[i] == max_cost
23
+ assert cost_vector[i]==control[i].size
24
+ end
25
+ #puts "%0#{n_agents}d" %i.to_s(2) + ": #{cost_vector[i]}"
26
+ end
27
+ precomputed_cost = "0000000000201000".split(//).collect{|x| x.to_i}
28
+ assert precomputed_cost == cost_vector,
29
+ precomputed_cost + cost_vector
30
+ assert ["", "", "", "", "", "", "", "", "", "", "", "", "1", "", "",
31
+ ""] == control
32
+ end
33
+ end
34
+ context "2 by 3 grid, 1 timestep " do
35
+ should "have these intial states with max cost" do
36
+ steps = 0
37
+ max_cost = (steps+1)*1 + 1
38
+ grid_hight = 2
39
+ grid_width = 3
40
+ n_agents = grid_width * grid_hight
41
+ runner = Cgl::Runner.new(steps, max_cost, grid_hight, grid_width)
42
+ result = runner.run
43
+ cost_vector = result[0]
44
+ control = result[1]
45
+ for i in 0..2**n_agents-1
46
+ unless cost_vector[i] == max_cost
47
+ assert cost_vector[i]==control[i].size
48
+ end
49
+ #puts "%0#{n_agents}d" %i.to_s(2) + ": #{cost_vector[i]}"
50
+ end
51
+
52
+ precomputed_cost =
53
+ "0000000002202000011010000000000002202000022020000220200010000000".split(//).collect{|x| x.to_i}
54
+ assert precomputed_cost == cost_vector,
55
+ precomputed_cost.to_s + "\n" + cost_vector.to_s
56
+ precomputed_control = ["", "", "", "", "", "", "", "", "", "", "", "",
57
+ "", "", "", "", "", "1", "1", "", "1", "", "", "", "", "", "", "", "",
58
+ "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
59
+ "", "", "", "", "", "", "", "", "", "1", "", "", "", "", "", "", ""]
60
+ assert precomputed_control == control, "control is wrong"
61
+ end
62
+ end
63
+ context "2 by 2 grid, 3 timestep " do
64
+ should "have these intial states with max cost" do
65
+ steps = 2
66
+ max_cost = (steps+1)*1 + 1
67
+ grid_size = 2
68
+ n_agents = grid_size**2
69
+ runner = Cgl::Runner.new(steps, max_cost, grid_size)
70
+ result = runner.run
71
+ assert_equal 2, result.size
72
+ cost_vector = result[0]
73
+ control = result[1]
74
+ assert_equal 2**n_agents, cost_vector.size
75
+ assert_equal 2**n_agents, control.size
76
+ for i in 0..2**n_agents-1
77
+ unless cost_vector[i] == max_cost
78
+ assert cost_vector[i]==control[i].size
79
+ end
80
+ end
81
+ precomputed_cost = "0000000000401000".split(//).collect{|x| x.to_i}
82
+ assert precomputed_cost == cost_vector,
83
+ precomputed_cost + cost_vector
84
+ assert ["", "", "", "", "", "", "", "", "", "", "", "", "1", "", "",
85
+ ""] == control
86
+ end
87
+ end
88
+ context "3 by 3 grid, 1 timestep " do
89
+ should "have these intial states with max cost" do
90
+ steps = 0
91
+ max_cost = (steps+1)*1 + 1
92
+ grid_size = 3
93
+ n_agents = grid_size**2
94
+ runner = Cgl::Runner.new(steps, max_cost, grid_size)
95
+ result = runner.run
96
+ assert_equal 2, result.size
97
+ cost_vector = result[0]
98
+ control = result[1]
99
+ assert_equal 2**n_agents, cost_vector.size
100
+ assert_equal 2**n_agents, control.size
101
+ for i in 0..2**n_agents-1
102
+ unless cost_vector[i] == max_cost
103
+ assert cost_vector[i]==control[i].size
104
+ end
105
+ #puts "%0#{n_agents}d" %i.to_s(2) + ": #{cost_vector[i]} control in step #{control[i]}"
106
+ end
107
+ # some hand crafted test cases
108
+ assert cost_vector[335] == 0
109
+ assert cost_vector[432] == 2
110
+ assert cost_vector[448] == 1
111
+ end
112
+ end
113
+ end
114
+
metadata ADDED
@@ -0,0 +1,81 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: optimal-control
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Franziska Hinkelmann
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-01-01 00:00:00 -05:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: |-
17
+ Simulate Conway's game of Life on a small grid with periodic
18
+ boundary conditions and find the optimal controller for the specified
19
+ control objective and control options
20
+ email: fhinkel@vt.edu
21
+ executables:
22
+ - optimalcontrol
23
+ extensions: []
24
+
25
+ extra_rdoc_files:
26
+ - CHANGELOG
27
+ - README
28
+ - bin/optimalcontrol
29
+ - lib/cgl/evaluate.rb
30
+ - lib/cgl/neighbors.rb
31
+ - lib/cgl/runner.rb
32
+ files:
33
+ - CHANGELOG
34
+ - Manifest
35
+ - README
36
+ - Rakefile
37
+ - bin/optimalcontrol
38
+ - lib/cgl/evaluate.rb
39
+ - lib/cgl/neighbors.rb
40
+ - lib/cgl/runner.rb
41
+ - test/test_evaluate.rb
42
+ - test/test_neighbors.rb
43
+ - test/test_runner.rb
44
+ - optimal-control.gemspec
45
+ has_rdoc: true
46
+ homepage: http://rubyforge.org/projects/optimal-control/
47
+ licenses: []
48
+
49
+ post_install_message:
50
+ rdoc_options:
51
+ - --line-numbers
52
+ - --inline-source
53
+ - --title
54
+ - Optimal-control
55
+ - --main
56
+ - README
57
+ require_paths:
58
+ - lib
59
+ required_ruby_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: "0"
64
+ version:
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: "1.2"
70
+ version:
71
+ requirements: []
72
+
73
+ rubyforge_project: optimal-control
74
+ rubygems_version: 1.3.5
75
+ signing_key:
76
+ specification_version: 3
77
+ summary: Simulate Conway's game of Life on a small grid with periodic boundary conditions and find the optimal controller for the specified control objective and control options
78
+ test_files:
79
+ - test/test_evaluate.rb
80
+ - test/test_neighbors.rb
81
+ - test/test_runner.rb