gene 0.0.1 → 0.1.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/Manifest +46 -0
- data/Rakefile +12 -9
- data/TODO +7 -0
- data/gene.gemspec +34 -0
- data/initializers/functional_extensions.rb +44 -0
- data/initializers/module_extensions.rb +14 -0
- data/initializers/object_extensions.rb +25 -0
- data/initializers/range_extensions.rb +9 -0
- data/initializers/runner.rb +15 -0
- data/initializers/symbol_extensions.rb +11 -0
- data/initializers/unbound_method_extensions.rb +3 -0
- data/lib/aligner.rb +34 -0
- data/lib/calculator.rb +42 -0
- data/lib/cell.rb +41 -0
- data/lib/color.rb +9 -0
- data/lib/dsl.rb +16 -0
- data/lib/gene.rb +67 -3
- data/lib/generator.rb +83 -0
- data/lib/geometry.rb +64 -0
- data/lib/hungarian.rb +205 -0
- data/lib/imagine.rb +22 -0
- data/lib/petri.rb +85 -0
- data/lib/point.rb +1 -0
- data/lib/trait.rb +60 -0
- data/tasks/test.rake +23 -0
- data/test/assets/Nova.jpg +0 -0
- data/test/assets/Rex.jpg +0 -0
- data/test/assets/Squares.jpg +0 -0
- data/test/test_helper.rb +6 -0
- data/test/unit/aligner_test.rb +91 -0
- data/test/unit/calculator_test.rb +100 -0
- data/test/unit/cell_test.rb +64 -0
- data/test/unit/color_test.rb +23 -0
- data/test/unit/dsl_test.rb +45 -0
- data/test/unit/functionals_extensions_test.rb +51 -0
- data/test/unit/gene_test.rb +76 -0
- data/test/unit/generator_test.rb +76 -0
- data/test/unit/geometry_test.rb +57 -0
- data/test/unit/hungarian_test.rb +196 -0
- data/test/unit/imagine_test.rb +54 -0
- data/test/unit/module_extensions_test.rb +40 -0
- data/test/unit/object_extensions_test.rb +34 -0
- data/test/unit/petri_test.rb +87 -0
- data/test/unit/range_extensions_test.rb +29 -0
- data/test/unit/symbol_extensions_test.rb +18 -0
- data/test/unit/trait_test.rb +97 -0
- data/test/unit/unbound_method_extensions_test.rb +11 -0
- metadata +118 -30
- data/History.txt +0 -6
- data/Manifest.txt +0 -7
- data/README.txt +0 -48
- data/bin/gene +0 -3
- data/test/test_gene.rb +0 -8
data/lib/point.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Point = Struct.new(:x, :y)
|
data/lib/trait.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
class Trait < Dsl
|
2
|
+
include Calculator
|
3
|
+
|
4
|
+
STANDARD_DEVIATION = {
|
5
|
+
:default => 0.1,
|
6
|
+
:range => 0.01..0.25
|
7
|
+
}
|
8
|
+
|
9
|
+
attr_reader :value, :range, :standard_deviation
|
10
|
+
|
11
|
+
def initialize(range)
|
12
|
+
@range = range
|
13
|
+
super
|
14
|
+
end
|
15
|
+
|
16
|
+
def mutated_value
|
17
|
+
new_value = value + standard_deviation * Trait.get_normal_random_variable
|
18
|
+
new_value = new_value.round if value.is_a?(Fixnum)
|
19
|
+
|
20
|
+
if new_value > range.max
|
21
|
+
range.max
|
22
|
+
elsif new_value < range.min
|
23
|
+
range.min
|
24
|
+
else
|
25
|
+
new_value
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def percentify
|
30
|
+
"#{value / range.max.to_f * 100}%"
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def finish_init
|
36
|
+
fill_out_value
|
37
|
+
fill_out_deviation
|
38
|
+
end
|
39
|
+
|
40
|
+
def fill_out_value
|
41
|
+
@value ||= Trait.generate_value(range.max)
|
42
|
+
end
|
43
|
+
|
44
|
+
def fill_out_deviation
|
45
|
+
@standard_deviation ||= STANDARD_DEVIATION[:default] * range.max
|
46
|
+
end
|
47
|
+
|
48
|
+
def new_standard_deviation_from(fitness)
|
49
|
+
deviation_range = STANDARD_DEVIATION[:range].max - STANDARD_DEVIATION[:range].min
|
50
|
+
STANDARD_DEVIATION[:range].max - deviation_range * fitness
|
51
|
+
end
|
52
|
+
|
53
|
+
def method_missing(name, *args, &block)
|
54
|
+
case name.to_s
|
55
|
+
when /^set_value$/: @value = args.first
|
56
|
+
when /^deviation$/: @standard_deviation = args.first * range.max
|
57
|
+
when /^deviate_from$/: @standard_deviation = new_standard_deviation_from(args.first)
|
58
|
+
else super end
|
59
|
+
end
|
60
|
+
end
|
data/tasks/test.rake
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
desc "Runs the test suite"
|
2
|
+
task :test do
|
3
|
+
require "benchmark"
|
4
|
+
|
5
|
+
totals = { :tests => 0, :assertions => 0, :failures => 0, :errors => 0 }
|
6
|
+
Benchmark.measure do
|
7
|
+
|
8
|
+
FileList["./test/**/*_test.rb"].map { |path| path.gsub("test/", "") }.each do |test|
|
9
|
+
results = `ruby -C test/ #{test}`
|
10
|
+
results =~ /(\d+) tests, (\d+) assertions, (\d+) failures, (\d+) errors/
|
11
|
+
|
12
|
+
totals[:tests] += $1.to_i
|
13
|
+
totals[:assertions] += $2.to_i
|
14
|
+
totals[:failures] += $3.to_i
|
15
|
+
totals[:errors] += $4.to_i
|
16
|
+
|
17
|
+
print "#{results}\n"
|
18
|
+
end
|
19
|
+
end.real.to_s.match(/(\d+\.\d{2})/)
|
20
|
+
|
21
|
+
print "Total results: #{totals[:tests]} tests run in #{$1} seconds: #{totals[:assertions]} assertions, #{totals[:failures]} failures, #{totals[:errors]} errors\n\n"
|
22
|
+
print "Your tests are #{totals[:failures].zero? && totals[:errors].zero? ? 'PASSING' : 'FAILING'}.\n"
|
23
|
+
end
|
Binary file
|
data/test/assets/Rex.jpg
ADDED
Binary file
|
Binary file
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "..", "test_helper.rb")
|
2
|
+
|
3
|
+
class AlignerTest < Test::Unit::TestCase
|
4
|
+
class TestClass
|
5
|
+
attr_accessor :cells
|
6
|
+
|
7
|
+
include Aligner
|
8
|
+
end
|
9
|
+
|
10
|
+
def setup
|
11
|
+
Petri.stubs(:image_dimensions).returns(Point.new(640, 480))
|
12
|
+
Petri.stubs(:num_genes).returns(3)
|
13
|
+
Petri.stubs(:num_points).returns(3)
|
14
|
+
|
15
|
+
@test_class = TestClass.new
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_true
|
19
|
+
assert true
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_align_crossover_for
|
23
|
+
@test_class.cells = [
|
24
|
+
Cell.new do
|
25
|
+
gene_0 &three_points_at(0, 0)
|
26
|
+
gene_1 &three_points_at(10, 0)
|
27
|
+
gene_2 &three_points_at(20, 0)
|
28
|
+
end,
|
29
|
+
Cell.new do
|
30
|
+
gene_0 &three_points_at(10, 0)
|
31
|
+
gene_1 &three_points_at(20, 0)
|
32
|
+
gene_2 &three_points_at(30, 0)
|
33
|
+
end
|
34
|
+
]
|
35
|
+
|
36
|
+
optimal_alignment = @test_class.align_crossover
|
37
|
+
|
38
|
+
assert_equal [0, 1, 2], optimal_alignment[:cell_1]
|
39
|
+
assert_equal [1, 0, 2], optimal_alignment[:cell_2]
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_crossover_map
|
43
|
+
Petri.stubs(:num_genes).returns(2)
|
44
|
+
|
45
|
+
@test_class.cells = [
|
46
|
+
Cell.new do
|
47
|
+
gene_0 &three_points_at(0, 0)
|
48
|
+
gene_1 &three_points_at(15, 0)
|
49
|
+
end,
|
50
|
+
Cell.new do
|
51
|
+
gene_0 &three_points_at(10, 0)
|
52
|
+
gene_1 &three_points_at(22.5, 0)
|
53
|
+
end
|
54
|
+
]
|
55
|
+
|
56
|
+
assert_equal [[10, 22.5], [5, 7.5]], @test_class.send(:crossover_map)
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_middle_point_of
|
60
|
+
Petri.stubs(:num_points).returns(4)
|
61
|
+
|
62
|
+
gene = Gene.new do
|
63
|
+
point_0 0, 0
|
64
|
+
point_1 30, 0
|
65
|
+
point_2 0, 15
|
66
|
+
point_3 30, 15
|
67
|
+
end
|
68
|
+
|
69
|
+
middle_point = @test_class.send(:middle_point_of, gene)
|
70
|
+
|
71
|
+
assert_equal 15, middle_point.x
|
72
|
+
assert_equal 7.5, middle_point.y
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_distance_between
|
76
|
+
point_1 = Point.new(0, 0)
|
77
|
+
point_2 = Point.new(3, 4)
|
78
|
+
|
79
|
+
assert_equal 5, @test_class.send(:distance_between, point_1, point_2)
|
80
|
+
end
|
81
|
+
|
82
|
+
protected
|
83
|
+
|
84
|
+
def three_points_at(x, y)
|
85
|
+
lambda do
|
86
|
+
point_0 x, y
|
87
|
+
point_1 x, y
|
88
|
+
point_2 x, y
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "..", "test_helper.rb")
|
2
|
+
|
3
|
+
class CalculatorTest < Test::Unit::TestCase
|
4
|
+
class TestClass
|
5
|
+
include Calculator
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_true
|
9
|
+
assert true
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_generate_value__raises_error_when_max_is_nil_or_zero
|
13
|
+
assert_raise ArgumentError do
|
14
|
+
TestClass.generate_value(nil)
|
15
|
+
end
|
16
|
+
|
17
|
+
assert_raise ArgumentError do
|
18
|
+
TestClass.generate_value(0)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_generate_value__returns_same_type_as_max
|
23
|
+
assert TestClass.generate_value(1.0).is_a?(Float)
|
24
|
+
assert TestClass.generate_value(100).is_a?(Fixnum)
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_get_normal_random_variable__x
|
28
|
+
sum = mock
|
29
|
+
sum.expects(:+).with(:y).returns(sum)
|
30
|
+
sum.expects(:<).with(1).returns(true)
|
31
|
+
|
32
|
+
x = mock
|
33
|
+
x.expects(:**).with(2).returns(sum)
|
34
|
+
y = mock
|
35
|
+
y.expects(:**).with(2).returns(:y)
|
36
|
+
|
37
|
+
TestClass.expects(:get_uniform_random_variable).twice.returns(x, y)
|
38
|
+
TestClass.expects(:rand).with(2).returns(0)
|
39
|
+
TestClass.expects(:convert).with(x, sum)
|
40
|
+
|
41
|
+
TestClass.get_normal_random_variable
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_get_normal_random_variable__y
|
45
|
+
sum = mock
|
46
|
+
sum.expects(:+).with(:y).returns(sum)
|
47
|
+
sum.expects(:<).with(1).returns(true)
|
48
|
+
|
49
|
+
x = mock
|
50
|
+
x.expects(:**).with(2).returns(sum)
|
51
|
+
y = mock
|
52
|
+
y.expects(:**).with(2).returns(:y)
|
53
|
+
|
54
|
+
TestClass.expects(:get_uniform_random_variable).twice.returns(x, y)
|
55
|
+
TestClass.expects(:rand).with(2).returns(1)
|
56
|
+
TestClass.expects(:convert).with(y, sum)
|
57
|
+
|
58
|
+
TestClass.get_normal_random_variable
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_get_normal_random_variable__loops_until_sum_is_less_than_one
|
62
|
+
sum = mock
|
63
|
+
sum.expects(:+).with(:y).returns(sum)
|
64
|
+
sum.expects(:<).with(1).returns(true)
|
65
|
+
|
66
|
+
x = mock
|
67
|
+
x.expects(:**).with(2).returns(sum)
|
68
|
+
y = mock
|
69
|
+
y.expects(:**).with(2).returns(:y)
|
70
|
+
|
71
|
+
TestClass.expects(:get_uniform_random_variable).times(4).returns(1, 1, x, y)
|
72
|
+
TestClass.expects(:rand).with(2).returns(0)
|
73
|
+
TestClass.expects(:convert).with(x, sum)
|
74
|
+
|
75
|
+
TestClass.get_normal_random_variable
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_get_uniform_random_variable
|
79
|
+
random_value = mock
|
80
|
+
random_value.expects(:*).with(:sign)
|
81
|
+
TestClass.expects(:rand).with(0).returns(random_value)
|
82
|
+
TestClass.expects(:random_sign_change).returns(:sign)
|
83
|
+
|
84
|
+
TestClass.get_uniform_random_variable
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_random_sign_change
|
88
|
+
TestClass.expects(:rand).with(2).returns(0)
|
89
|
+
assert_equal 1, TestClass.send(:random_sign_change)
|
90
|
+
|
91
|
+
TestClass.expects(:rand).with(2).returns(1)
|
92
|
+
assert_equal -1, TestClass.send(:random_sign_change)
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_convert
|
96
|
+
assert_equal 0, TestClass.send(:convert, 1, 0)
|
97
|
+
assert_equal 0, TestClass.send(:convert, 0, 0)
|
98
|
+
assert_equal 0, TestClass.send(:convert, 0, 1)
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "..", "test_helper.rb")
|
2
|
+
|
3
|
+
class CellTest < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
Petri.stubs(:image_dimensions).returns(Point.new(640, 480))
|
6
|
+
Petri.stubs(:num_genes).returns(3)
|
7
|
+
Petri.stubs(:num_points).returns(3)
|
8
|
+
|
9
|
+
@cell = Cell.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_true
|
13
|
+
assert true
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_initialize
|
17
|
+
image_range_x = 0...Petri.image_dimensions.x
|
18
|
+
image_range_y = 0...Petri.image_dimensions.y
|
19
|
+
channel_range = 0.0..1.0
|
20
|
+
|
21
|
+
@cell.genes.each do |gene|
|
22
|
+
assert_equal Petri.num_points, gene.polygon.num_points
|
23
|
+
|
24
|
+
assert gene.polygon.points.all? { |point| image_range_x.include?(point.x.value) && image_range_y.include?(point.y.value) }
|
25
|
+
assert gene.color.each_pair { |channel, trait| channel_range.include?(trait.value) }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_initialize__with_block
|
30
|
+
lambda { |index| assert Cell.new.genes[index].is_a?(Gene) } | Petri.num_genes.times
|
31
|
+
|
32
|
+
assert_raise NoMethodError do
|
33
|
+
Cell.new { rawr! }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_genes_by_alpha
|
38
|
+
cell = Cell.new do
|
39
|
+
gene_0 do
|
40
|
+
trait_a do
|
41
|
+
set_value 0.5
|
42
|
+
end
|
43
|
+
end
|
44
|
+
gene_1 do
|
45
|
+
trait_a do
|
46
|
+
set_value 0.0
|
47
|
+
end
|
48
|
+
end
|
49
|
+
gene_2 do
|
50
|
+
trait_a do
|
51
|
+
set_value 1.0
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
assert_equal [0.5, 0.0, 1.0], cell.genes.map(&:color).map(&:a).map(&:value)
|
57
|
+
assert_equal [1.0, 0.5, 0.0], cell.genes_by_alpha.map(&:color).map(&:a).map(&:value)
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_genes_from_alignment_map
|
61
|
+
cell = Cell.new
|
62
|
+
assert_equal [cell.genes[2], cell.genes[0], cell.genes[1]], cell.genes_from_alignment_map([2, 0, 1])
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "..", "test_helper.rb")
|
2
|
+
|
3
|
+
class ColorTest < Test::Unit::TestCase
|
4
|
+
def test_true
|
5
|
+
assert true
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_rgb
|
9
|
+
color = Color.new(:r, :g, :b, :a)
|
10
|
+
assert_equal [:r, :g, :b], color.rgb
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_rgba_format
|
14
|
+
color = Color.new(
|
15
|
+
Trait.new(0.0..1.0) { set_value 0 },
|
16
|
+
Trait.new(0.0..1.0) { set_value 0.25 },
|
17
|
+
Trait.new(0.0..1.0) { set_value 0.5 },
|
18
|
+
Trait.new(0.0..1.0) { set_value 0.75 }
|
19
|
+
)
|
20
|
+
|
21
|
+
assert_equal "rgba(0.0%, 25.0%, 50.0%, 0.75)", color.rgba_format
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "..", "test_helper.rb")
|
2
|
+
|
3
|
+
class DslTest < Test::Unit::TestCase
|
4
|
+
class TestClass < Dsl
|
5
|
+
def initialize
|
6
|
+
@set_in_init = true
|
7
|
+
super
|
8
|
+
end
|
9
|
+
|
10
|
+
def finish_init
|
11
|
+
@set_in_finish_init = true
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def setup
|
16
|
+
@test_class = TestClass.new do
|
17
|
+
@set_in_block = true
|
18
|
+
method_in_binding_scope
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_true
|
23
|
+
assert true
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_dsl__self_changed_in_block
|
27
|
+
%w[init finish_init block].each do |suffix|
|
28
|
+
assert @test_class.instance_variable_get(:"@set_in_#{suffix}")
|
29
|
+
end
|
30
|
+
|
31
|
+
assert_raise NoMethodError do
|
32
|
+
TestClass.new { rawr! }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_dsl__method_resolution_in_binding_scope
|
37
|
+
assert @set_in_binding_scope
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def method_in_binding_scope
|
43
|
+
@set_in_binding_scope = true
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "..", "test_helper.rb")
|
2
|
+
|
3
|
+
class FunctionalExtensionsTest < Test::Unit::TestCase
|
4
|
+
def test_true
|
5
|
+
assert true
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_apply
|
9
|
+
sum = lambda { |x, y| x + y }
|
10
|
+
|
11
|
+
assert_equal [3, 7], sum | [[1, 2], [3, 4]]
|
12
|
+
assert_equal [3, 7], sum.apply([[1, 2], [3, 4]])
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_reduce
|
16
|
+
sum = lambda { |x, y| x + y }
|
17
|
+
|
18
|
+
assert_equal 10, sum <= [1, 2, 3, 4]
|
19
|
+
assert_equal 10, sum.reduce([1, 2, 3, 4])
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_compose
|
23
|
+
add_1 = lambda { |x| x + 1 }
|
24
|
+
double = lambda { |x| x * 2 }
|
25
|
+
|
26
|
+
assert_equal 5, (add_1 * double)[2]
|
27
|
+
assert_equal 5, (add_1.compose(double))[2]
|
28
|
+
|
29
|
+
assert_equal 6, (double * add_1)[2]
|
30
|
+
assert_equal 6, (double.compose(add_1))[2]
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
def test_apply_head
|
35
|
+
function = lambda { |x, y, z| x * y + z }
|
36
|
+
assert_equal 24, (function >> 5)[4, 4]
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_apply_tail
|
40
|
+
function = lambda { |x, y, z| x * y + z }
|
41
|
+
assert_equal 21, (function << 5)[4, 4]
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_memoize
|
45
|
+
factorial = +lambda { |x| x == 1 ? 1 : x * factorial[x - 1] }
|
46
|
+
assert_equal 120, factorial[5]
|
47
|
+
|
48
|
+
factorial = lambda { |x| x == 1 ? 1 : x * factorial[x - 1] }.memoize
|
49
|
+
assert_equal 120, factorial[5]
|
50
|
+
end
|
51
|
+
end
|