answer-factory 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE.txt +21 -0
- data/Rakefile +29 -0
- data/Thorfile +79 -0
- data/VERSION +1 -0
- data/_spikes/old_vs_new_dominated_by?.rb +45 -0
- data/config/database.yml +9 -0
- data/lib/answer-factory.rb +14 -0
- data/lib/answers/answer.rb +126 -0
- data/lib/answers/batch.rb +49 -0
- data/lib/factories/factory.rb +53 -0
- data/lib/factories/workstation.rb +33 -0
- data/lib/operators/basic_operators.rb +240 -0
- data/lib/operators/evaluators.rb +113 -0
- data/lib/operators/samplers_and_selectors.rb +131 -0
- data/pkg/nudgegp-0.0.1.gem +0 -0
- data/readme.md +29 -0
- data/spec/answer_spec.rb +412 -0
- data/spec/batch_spec.rb +98 -0
- data/spec/config_spec.rb +94 -0
- data/spec/factories/factory_spec.rb +86 -0
- data/spec/factories/workstation_spec.rb +139 -0
- data/spec/operators/any_one_sampler_spec.rb +39 -0
- data/spec/operators/dominated_quantile_spec.rb +111 -0
- data/spec/operators/duplicate_genomes_spec.rb +35 -0
- data/spec/operators/evaluators/program_point_evaluator_spec.rb +43 -0
- data/spec/operators/evaluators/test_case_evaluator_spec.rb +129 -0
- data/spec/operators/infrastructure_spec.rb +45 -0
- data/spec/operators/most_dominated_subset_spec.rb +47 -0
- data/spec/operators/nondominated_subset_spec.rb +103 -0
- data/spec/operators/pointCrossover_spec.rb +60 -0
- data/spec/operators/pointDeletion_spec.rb +62 -0
- data/spec/operators/pointMutation_spec.rb +77 -0
- data/spec/operators/random_guess_spec.rb +77 -0
- data/spec/operators/resample_and_clone_spec.rb +60 -0
- data/spec/operators/resample_values_spec.rb +135 -0
- data/spec/operators/uniformBackboneCrossover_spec.rb +67 -0
- data/spec/spec_helper.rb +14 -0
- metadata +201 -0
@@ -0,0 +1,62 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "./../spec_helper")
|
2
|
+
|
3
|
+
|
4
|
+
describe "PointDeleteOperator search operator" do
|
5
|
+
describe "generate" do
|
6
|
+
before(:each) do
|
7
|
+
@zapper = PointDeleteOperator.new()
|
8
|
+
@dude1 = Answer.new("block { do thing1 \n do thing2 \n do thing3}")
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should accept a Batch as a param" do
|
12
|
+
lambda{@zapper.generate()}.should raise_error(ArgumentError)
|
13
|
+
lambda{@zapper.generate(812)}.should raise_error(ArgumentError)
|
14
|
+
lambda{@zapper.generate(Batch.new)}.should_not raise_error(ArgumentError)
|
15
|
+
lambda{@zapper.generate(Batch[@dude1])}.should_not raise_error(ArgumentError)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should raise an Argument error if all contents of the crowd aren't Answers" do
|
19
|
+
lambda{@zapper.generate([])}.should_not raise_error(ArgumentError)
|
20
|
+
lambda{@zapper.generate([ 77 ])}.should raise_error(ArgumentError)
|
21
|
+
lambda{@zapper.generate([ @dude1, 77 ])}.should raise_error(ArgumentError)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should return a Batch as a result" do
|
25
|
+
@zapper.generate([@dude1]).should be_a_kind_of(Batch)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should use Answer#delete_point to produce the variants" do
|
29
|
+
@dude1.should_receive(:delete_point_or_clone).and_return("do parseable")
|
30
|
+
@zapper.generate([@dude1])
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should produce one result per individual in the wildtype crowd as a default" do
|
34
|
+
@zapper.generate([@dude1]).length.should == 1
|
35
|
+
@zapper.generate([@dude1, @dude1]).length.should == 2
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should produce more if passed the optional howManyCopies parameter > 1" do
|
39
|
+
@zapper.generate([@dude1],2).length.should == 2
|
40
|
+
@zapper.generate([@dude1, @dude1],3).length.should == 6
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should produce individuals from which a random point (and its subpoints) is deleted" do
|
44
|
+
@zapper.generate([@dude1],5).each {|baby| baby.points.should < @dude1.points}
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should produce 'block {}' whenever a root is deleted" do
|
48
|
+
@zapper.should_receive(:rand).with(4).and_return(0)
|
49
|
+
@zapper.generate([@dude1])[0].blueprint.should == "block {}"
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should increment the progress of the offspring" do
|
53
|
+
@dude1.stub(:progress).and_return(195)
|
54
|
+
@zapper.generate([@dude1])[0].progress.should == 196
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should handle moving the footnotes correctly"
|
58
|
+
|
59
|
+
it "should maintain unused footnotes correctly"
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "./../spec_helper")
|
2
|
+
|
3
|
+
|
4
|
+
describe "PointMutationOperator" do
|
5
|
+
describe "initialization" do
|
6
|
+
it "should have a params attribute when created that sets basic values for code generation" do
|
7
|
+
PointMutationOperator.new.incoming_options.should == {}
|
8
|
+
mutator = PointMutationOperator.new(:points => 3, :blocks => 1)
|
9
|
+
mutator.incoming_options.should_not == {}
|
10
|
+
mutator.incoming_options[:points].should == 3
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "generate" do
|
15
|
+
before(:each) do
|
16
|
+
@gammaray = PointMutationOperator.new(target_size_in_points: 3, types_name: ["int"])
|
17
|
+
@dude1 = Answer.new("block { do x1 \n do x2 \n do x3}")
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should accept an Array of one or more Answers as a param" do
|
21
|
+
lambda{@gammaray.generate()}.should raise_error(ArgumentError)
|
22
|
+
lambda{@gammaray.generate(99)}.should raise_error(ArgumentError)
|
23
|
+
lambda{@gammaray.generate([])}.should raise_error(ArgumentError)
|
24
|
+
lambda{@gammaray.generate([99])}.should raise_error(ArgumentError)
|
25
|
+
|
26
|
+
lambda{@gammaray.generate([@dude1])}.should_not raise_error(ArgumentError)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should return a Batch as a result" do
|
30
|
+
@gammaray.generate([@dude1]).should be_a_kind_of(Batch)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should use Answer#replace_point to produce the variants" do
|
34
|
+
@dude1.should_receive(:replace_point_or_clone).and_return("do anything")
|
35
|
+
@gammaray.generate([@dude1])
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should produce one result per individual in the wildtype crowd as a default" do
|
39
|
+
@gammaray.generate([@dude1]).length.should == 1
|
40
|
+
@gammaray.generate([@dude1,@dude1]).length.should == 2
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should produce more if passed the optional howManyCopies parameter > 1" do
|
44
|
+
@gammaray.generate([@dude1],3).length.should == 3
|
45
|
+
@gammaray.generate([@dude1,@dude1],2).length.should == 4
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should produce individuals from which a random point (and all subpoints) is replaced" do
|
49
|
+
@gammaray.should_receive(:rand).and_return(0)
|
50
|
+
@gammaray.generate([@dude1])[0].points.should == 3 # totally replaced with 3-pt code
|
51
|
+
@gammaray.should_receive(:rand).and_return(1)
|
52
|
+
@gammaray.generate([@dude1])[0].points.should == 6 #replace point 2 with 3-pt code
|
53
|
+
@gammaray.should_receive(:rand).and_return(2)
|
54
|
+
@gammaray.generate([@dude1])[0].points.should == 6 #replace point 3 with 3-pt code
|
55
|
+
@gammaray.should_receive(:rand).and_return(3)
|
56
|
+
@gammaray.generate([@dude1])[0].points.should == 6 #replace point 4 with 3-pt code
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should accept temporarily overriding params to pass into CodeType.random_value" do
|
60
|
+
@gammaray.should_receive(:rand).and_return(0)
|
61
|
+
@gammaray.generate([@dude1])[0].points.should == 3 # totally replaced with 3-pt code
|
62
|
+
@gammaray.should_receive(:rand).and_return(0)
|
63
|
+
@gammaray.generate([@dude1],1,target_size_in_points: 10)[0].points.should == 10
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should increment the #progress of the offspring" do
|
67
|
+
@dude1.stub(:progress).and_return(888)
|
68
|
+
@gammaray.generate([@dude1],13).each {|baby| baby.progress.should == 889}
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should handle moving the footnotes correctly"
|
72
|
+
|
73
|
+
it "should maintain unused footnotes correctly"
|
74
|
+
|
75
|
+
it "should introduce new footnotes smoothly, if a ValuePoint is added"
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
#encoding:utf-8
|
2
|
+
require File.join(File.dirname(__FILE__), "./../spec_helper")
|
3
|
+
|
4
|
+
|
5
|
+
describe "random_guess operator" do
|
6
|
+
before(:each) do
|
7
|
+
@myGuesser = RandomGuessOperator.new
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should be a kind of SearchOperator" do
|
11
|
+
@myGuesser.should be_a_kind_of(SearchOperator)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should have a params attribute when created that sets basic values for code generation" do
|
15
|
+
RandomGuessOperator.new.incoming_options.should == {}
|
16
|
+
thisGuesser = RandomGuessOperator.new(foo:99, bar:101)
|
17
|
+
thisGuesser.incoming_options.should_not == {}
|
18
|
+
thisGuesser.incoming_options[:foo].should == 99
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
it "should produce a Batch of Answers when it receives #generate" do
|
23
|
+
newDudes = @myGuesser.generate
|
24
|
+
newDudes.should be_a_kind_of(Batch)
|
25
|
+
newDudes[0].should be_a_kind_of(Answer)
|
26
|
+
newDudes[0].blueprint.should_not == nil
|
27
|
+
newDudes[0].program.should_not == nil
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should produce one as a default, more if a higher number is passed in" do
|
31
|
+
@myGuesser.generate.length.should == 1
|
32
|
+
@myGuesser.generate(4).length.should == 4
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should have a parsed blueprint as its #program attribute" do
|
36
|
+
newDudes = @myGuesser.generate
|
37
|
+
newDudes[0].program.should be_a_kind_of(NudgeProgram)
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should accept temporarily overriding options to pass into CodeType.any_value" do
|
41
|
+
@myNewGuesser = RandomGuessOperator.new(
|
42
|
+
target_size_in_points: 7,
|
43
|
+
instruction_names: ["int_add", "int_subtract"],
|
44
|
+
reference_names: ["x1", "x2", "x3"])
|
45
|
+
|
46
|
+
lambda{@myNewGuesser.generate(
|
47
|
+
3,
|
48
|
+
target_size_in_points: 12,
|
49
|
+
reference_names: ["y1"])}.should_not raise_error
|
50
|
+
|
51
|
+
@myNewGuesser.generate(
|
52
|
+
3,
|
53
|
+
target_size_in_points: 12)[0].program.points.should_not == 7
|
54
|
+
|
55
|
+
@myNewGuesser.generate(
|
56
|
+
3,
|
57
|
+
target_size_in_points: 12)[0].program.points.should == 12
|
58
|
+
|
59
|
+
@myNewGuesser.generate(
|
60
|
+
1,
|
61
|
+
target_size_in_points: 16,
|
62
|
+
probabilities:{b:0,r:1,v:0,i:0},
|
63
|
+
reference_names: ["y1"])[0].blueprint.should include("y1")
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should produce a Batch that contains Answers with progress=0 only" do
|
67
|
+
@myGuesser.generate(12).each {|dude| dude.progress.should == 0}
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should handle generated footnotes correctly" do
|
71
|
+
@myGuesser.generate(1,
|
72
|
+
target_size_in_points: 52,
|
73
|
+
type_names:["int"],
|
74
|
+
probabilities: {b:0,v:1,i:0,r:0})[0].program.footnote_section.scan(/«int»/).length.should == 51
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "./../spec_helper")
|
2
|
+
|
3
|
+
|
4
|
+
describe "resample_and_clone operator" do
|
5
|
+
before(:each) do
|
6
|
+
@myGuesser = RandomGuessOperator.new(type_names: ["int"], instruction_names: ["int_add"])
|
7
|
+
@mySampler = ResampleAndCloneOperator.new
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should be a kind of SearchOperator" do
|
11
|
+
@mySampler.should be_a_kind_of(SearchOperator)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should produce a list of Answers when it receives #generate" do
|
15
|
+
newDudes = @mySampler.generate(@myGuesser.generate(3))
|
16
|
+
newDudes.should be_a_kind_of(Batch)
|
17
|
+
newDudes[0].should be_a_kind_of(Answer)
|
18
|
+
newDudes[0].blueprint.should_not == nil
|
19
|
+
newDudes[0].program.should_not == nil
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should produce one Answer with a blueprint identical to one of the passed in crowd's" do
|
23
|
+
pop = @myGuesser.generate(1)
|
24
|
+
newDudes = @mySampler.generate(pop)
|
25
|
+
newDudes[0].blueprint.should == pop[0].blueprint
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should return more than one individual when asked to, resampling as needed" do
|
29
|
+
newDudes = @mySampler.generate(@myGuesser.generate(10))
|
30
|
+
newDudes.length.should == 1
|
31
|
+
newDudes = @mySampler.generate(@myGuesser.generate(3),2)
|
32
|
+
newDudes.length.should == 2
|
33
|
+
newDudes = @mySampler.generate(@myGuesser.generate(1),2)
|
34
|
+
newDudes.length.should == 2
|
35
|
+
newDudes[0].blueprint.should == newDudes[1].blueprint
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should not return links to the original program copies in the new clones" do
|
39
|
+
pop = @myGuesser.generate(3)
|
40
|
+
newDudes = @mySampler.generate(pop)
|
41
|
+
pop.collect {|old_dude| old_dude.program.object_id}.should_not include(newDudes[0].program.object_id)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should have a parsed blueprint as its #program attribute" do
|
45
|
+
pop = @myGuesser.generate(3)
|
46
|
+
newDudes = @mySampler.generate(pop)
|
47
|
+
newDudes[0].program.should be_a_kind_of(NudgeProgram)
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should increment the #progress of each clone" do
|
51
|
+
pop = @myGuesser.generate(3)
|
52
|
+
pop.each {|donor| donor.stub(:progress).and_return(12)}
|
53
|
+
newDudes = @mySampler.generate(pop)
|
54
|
+
newDudes.each {|kid| kid.progress.should == 13}
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should handle footnotes correctly"
|
58
|
+
|
59
|
+
it "should use a deep copy to clone new guys, not just clone"
|
60
|
+
end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
#encoding: utf-8
|
2
|
+
require File.join(File.dirname(__FILE__), "./../spec_helper")
|
3
|
+
|
4
|
+
|
5
|
+
describe "ResampleValuesOperator search operator" do
|
6
|
+
|
7
|
+
it "should not need any initial parameters" do
|
8
|
+
lambda{ResampleValuesOperator.new()}.should_not raise_error
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should be possible to pass in stored parameters" do
|
12
|
+
lambda{ResampleValuesOperator.new(randomIntegerLowerBound: 12)}.should_not raise_error
|
13
|
+
rs = ResampleValuesOperator.new({boolTrueProbability: 0.2})
|
14
|
+
rs.incoming_options.should include(:boolTrueProbability)
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "generate" do
|
18
|
+
before(:each) do
|
19
|
+
@rs = ResampleValuesOperator.new({boolTrueProbability: 0.2})
|
20
|
+
@intDude = Answer.new("block {value «int»}\n«int» 3")
|
21
|
+
@boolDude = Answer.new("block {value «bool»}\n«bool» false")
|
22
|
+
@floatDude = Answer.new("block {value «float»}\n«float» -991.2213")
|
23
|
+
@complicatedDude = Answer.new(
|
24
|
+
"block {value «int» value «bool» block {value «float»}}\n«int» 3\n«bool» false\n«float» 0.0")
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should require a Batch as a first parameter" do
|
28
|
+
lambda{@rs.generate()}.should raise_error(ArgumentError)
|
29
|
+
lambda{@rs.generate(Batch.new)}.should_not raise_error(ArgumentError)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should raise an ArgumentError if the array parameter isn't all Answers" do
|
33
|
+
lambda{@rs.generate([88])}.should raise_error(ArgumentError)
|
34
|
+
lambda{@rs.generate([@intDude])}.should_not raise_error(ArgumentError)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should by default produce one (1) resampled mutant for each input" do
|
38
|
+
@rs.generate([@intDude]).length.should == 1
|
39
|
+
@rs.generate([@intDude, @intDude]).length.should == 2
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should call #any_value for each line in each individual that is a 'sample'" do
|
43
|
+
IntType.should_receive(:any_value).and_return(777)
|
44
|
+
newGuys = @rs.generate([@intDude])
|
45
|
+
|
46
|
+
BoolType.should_receive(:any_value).and_return(false)
|
47
|
+
newGuys = @rs.generate([@boolDude])
|
48
|
+
|
49
|
+
FloatType.should_receive(:any_value).and_return(9.999)
|
50
|
+
newGuys = @rs.generate([@floatDude])
|
51
|
+
|
52
|
+
IntType.should_receive(:any_value).and_return(777)
|
53
|
+
BoolType.should_receive(:any_value).and_return(false)
|
54
|
+
FloatType.should_receive(:any_value).and_return(9.999)
|
55
|
+
newGuys = @rs.generate([@complicatedDude])
|
56
|
+
|
57
|
+
IntType.should_receive(:any_value).and_return(1,2)
|
58
|
+
BoolType.should_receive(:any_value).and_return(false,true)
|
59
|
+
FloatType.should_receive(:any_value).and_return(1.0,2.0)
|
60
|
+
oldGuys = [@intDude,@boolDude,@floatDude,@complicatedDude]
|
61
|
+
newGuys = @rs.generate(oldGuys,1)
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should be possible to pass in a higher integer, and get that many variants for each input" do
|
65
|
+
IntType.should_receive(:any_value).and_return(11,22,33)
|
66
|
+
newGuys = @rs.generate([@intDude],3)
|
67
|
+
newGuys[0].blueprint.should include("11")
|
68
|
+
newGuys[1].blueprint.should include("22")
|
69
|
+
newGuys[2].blueprint.should include("33")
|
70
|
+
|
71
|
+
IntType.should_receive(:any_value).and_return(4,5,6,7)
|
72
|
+
newGuys = @rs.generate([@intDude, @intDude],2)
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should be using the Operator's saved parameters as a default behavior" do
|
76
|
+
wholeLottaParams = {
|
77
|
+
:randomIntegerLowerBound => 1000,
|
78
|
+
:randomIntegerUpperBound => 1005,
|
79
|
+
:randomBooleanTruthProb => 0.2,
|
80
|
+
:randomFloatLowerBound => 112.0,
|
81
|
+
:randomFloatUpperBound => 112.5}
|
82
|
+
|
83
|
+
resampleLimited = ResampleValuesOperator.new(wholeLottaParams)
|
84
|
+
|
85
|
+
IntType.should_receive(:any_value).with(hash_including(wholeLottaParams))
|
86
|
+
newGuys = resampleLimited.generate([@intDude])
|
87
|
+
|
88
|
+
BoolType.should_receive(:any_value).with(hash_including(wholeLottaParams))
|
89
|
+
newGuys = resampleLimited.generate([@boolDude])
|
90
|
+
|
91
|
+
FloatType.should_receive(:any_value).with(hash_including(wholeLottaParams))
|
92
|
+
newGuys = resampleLimited.generate([@floatDude])
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should return Answers who (probably) differ from the originals passed in" do
|
96
|
+
outOfRangeParams = {
|
97
|
+
:randomIntegerLowerBound => 1000,
|
98
|
+
:randomIntegerUpperBound => 1005,
|
99
|
+
:randomBooleanTruthProb => 1.0,
|
100
|
+
:randomFloatLowerBound => 112.0,
|
101
|
+
:randomFloatUpperBound => 112.5}
|
102
|
+
resampleFarAway = ResampleValuesOperator.new(outOfRangeParams)
|
103
|
+
newGuys = resampleFarAway.generate([@intDude])
|
104
|
+
newGuys[0].blueprint.should =~ /100[0-5]/
|
105
|
+
newGuys = resampleFarAway.generate([@boolDude])
|
106
|
+
newGuys[0].blueprint.should =~ /true/
|
107
|
+
newGuys = resampleFarAway.generate([@floatDude])
|
108
|
+
newGuys[0].blueprint.should =~ /112\.[0-5]/
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should be possible to temporarily override some or all of the preset @params" do
|
112
|
+
bigInt = {:randomIntegerLowerBound => 90000,:randomIntegerUpperBound => 91000}
|
113
|
+
toBeOverridden = ResampleValuesOperator.new(bigInt)
|
114
|
+
defaults = toBeOverridden.generate([@intDude],5)
|
115
|
+
defaults.each {|dude| dude.blueprint.should =~ /9\d\d\d\d/}
|
116
|
+
|
117
|
+
littler = toBeOverridden.generate([@intDude],5,
|
118
|
+
:randomIntegerLowerBound => -19, :randomIntegerUpperBound => -10)
|
119
|
+
littler.each {|dude| dude.blueprint.should =~ /-1\d/}
|
120
|
+
end
|
121
|
+
|
122
|
+
it "should increment the #progress of every clone" do
|
123
|
+
@complicatedDude.stub!(:progress).and_return(192)
|
124
|
+
@rs.generate([@complicatedDude],5).each {|clone| clone.progress.should == 193}
|
125
|
+
end
|
126
|
+
|
127
|
+
it "should leave unrecognized types with footnote values in place" do
|
128
|
+
hunh = Answer.new("value «foo»\n«foo» bar")
|
129
|
+
ResampleValuesOperator.new.generate([hunh])[0].blueprint.should include("bar")
|
130
|
+
end
|
131
|
+
|
132
|
+
it "should work with CodeType footnotes, and reduce the number of points in each successive call"
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "./../spec_helper")
|
2
|
+
|
3
|
+
|
4
|
+
describe "UniformBackboneCrossoverOperator" do
|
5
|
+
before(:each) do
|
6
|
+
@newDudes = []
|
7
|
+
@options = {target_size_in_points: 6, instruction_names: ["a", "b", "c"], type_names: ["int"]}
|
8
|
+
@myXover = UniformBackboneCrossoverOperator.new
|
9
|
+
@myGuesser = RandomGuessOperator.new(@options)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should be a kind of SearchOperator" do
|
13
|
+
@myXover.should be_a_kind_of(SearchOperator)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should produce a Batch of Answers when it receives #generate" do
|
17
|
+
@newDudes = @myXover.generate(@myGuesser.generate(2))
|
18
|
+
@newDudes.should be_a_kind_of(Batch)
|
19
|
+
@newDudes.each {|dude| dude.should be_a_kind_of(Answer)}
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should produce the same number of Answers it gets as a default" do
|
23
|
+
@newDudes = @myXover.generate(@myGuesser.generate(6))
|
24
|
+
@newDudes.length.should == 6
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should have an optional parameter that specifies the number of offspring to produce" do
|
28
|
+
@newDudes = @myXover.generate(@myGuesser.generate(2),5)
|
29
|
+
@newDudes.length.should == 5
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should only include backbone points from one of the parents in the offsprings' genomes" do
|
33
|
+
rents = @myGuesser.generate(2)
|
34
|
+
@newDudes = @myXover.generate(rents,1)
|
35
|
+
@newDudes.length.should == 1
|
36
|
+
allParentalPoints = rents[0].program[1].contents + rents[1].program[1].contents
|
37
|
+
allTidied = allParentalPoints.collect {|pt| "#{pt.tidy}<br />"}
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should return an identical individual if given only one parent" do
|
41
|
+
rent = @myGuesser.generate(1)
|
42
|
+
@newDudes = @myXover.generate(rent,3)
|
43
|
+
@newDudes.each {|kid| kid.program.tidy.should == rent[0].program.tidy}
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
it "should not affect the original parents set in any way" do
|
48
|
+
rents = @myGuesser.generate(2)
|
49
|
+
originalMom = rents[0].object_id
|
50
|
+
@newDudes = @myXover.generate(rents,1)
|
51
|
+
rents[0].object_id.should == originalMom
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should return offspring with #progress values incremented from the largest parent value" do
|
55
|
+
rents = @myGuesser.generate(2)
|
56
|
+
rents[0].should_receive(:progress).at_least(1).times.and_return(12)
|
57
|
+
rents[1].should_receive(:progress).at_least(1).times.and_return(33)
|
58
|
+
@newDudes = @myXover.generate(rents,20)
|
59
|
+
@newDudes.each {|baby| [13, 34].should include(baby.progress)}
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should handle moving the footnotes correctly"
|
63
|
+
|
64
|
+
it "should maintain unused footnotes correctly"
|
65
|
+
|
66
|
+
|
67
|
+
end
|