answer-factory 0.0.1
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/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
|