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