answer-factory 0.0.9 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. data/Rakefile +1 -0
  2. data/Thorfile +9 -6
  3. data/VERSION +1 -1
  4. data/answer-factory.gemspec +20 -5
  5. data/lib/answer-factory.rb +14 -2
  6. data/lib/answers/answer.rb +17 -3
  7. data/lib/answers/batch.rb +15 -3
  8. data/lib/factories/workstation.rb +50 -1
  9. data/lib/operators/all_duplicated_genomes_sampler.rb +14 -0
  10. data/lib/operators/any_one_sampler.rb +7 -0
  11. data/lib/operators/dominated_quantile_selector.rb +16 -0
  12. data/lib/operators/infrastructure.rb +74 -0
  13. data/lib/operators/most_dominated_subset_sampler.rb +13 -0
  14. data/lib/operators/nondominated_subset_selector.rb +17 -0
  15. data/lib/operators/point_crossover_operator.rb +24 -0
  16. data/lib/operators/point_delete_operator.rb +19 -0
  17. data/lib/operators/point_mutation_operator.rb +22 -0
  18. data/lib/operators/program_point_count_evaluator.rb +14 -0
  19. data/lib/operators/random_guess_operator.rb +30 -0
  20. data/lib/operators/resample_and_clone_operator.rb +28 -0
  21. data/lib/operators/resample_values_operator.rb +40 -0
  22. data/lib/operators/{evaluators.rb → test_case_evaluator.rb} +3 -34
  23. data/lib/operators/uniform_backbone_crossover_operator.rb +53 -0
  24. data/readme.md +28 -3
  25. data/spec/answer_spec.rb +33 -1
  26. data/spec/batch_spec.rb +25 -12
  27. data/spec/factories/factory_spec.rb +53 -36
  28. data/spec/factories/workstation_spec.rb +194 -20
  29. data/spec/operators/evaluators/program_point_evaluator_spec.rb +1 -1
  30. data/spec/operators/evaluators/test_case_evaluator_spec.rb +2 -2
  31. data/spec/operators/nondominated_subset_spec.rb +8 -8
  32. data/spec/operators/random_guess_spec.rb +16 -11
  33. data/spec/operators/resample_and_clone_spec.rb +8 -8
  34. data/spec/operators/uniformBackboneCrossover_spec.rb +7 -7
  35. data/spec/spec_helper.rb +1 -0
  36. metadata +38 -12
  37. data/lib/operators/basic_operators.rb +0 -240
  38. data/lib/operators/samplers_and_selectors.rb +0 -131
@@ -1,5 +1,6 @@
1
1
  require File.join(File.dirname(__FILE__), "./../spec_helper")
2
2
 
3
+
3
4
  describe "Workstation" do
4
5
 
5
6
  describe "names" do
@@ -37,7 +38,6 @@ describe "Workstation" do
37
38
  end
38
39
 
39
40
 
40
-
41
41
  describe "capacity" do
42
42
  it "should accept a #capacity attribute in initialization" do
43
43
  w1 = Workstation.new(:ws, capacity:12)
@@ -62,8 +62,8 @@ describe "Workstation" do
62
62
 
63
63
 
64
64
  describe "answers" do
65
- it "should be an Array that's empty initially" do
66
- Workstation.new(:place).answers.should == []
65
+ it "should be a Batch that's empty initially" do
66
+ Workstation.new(:place).answers.should be_a_kind_of(Batch)
67
67
  end
68
68
  end
69
69
 
@@ -92,7 +92,6 @@ describe "Workstation" do
92
92
 
93
93
 
94
94
 
95
-
96
95
  describe "#cycle" do
97
96
  it "should invoke #receive!, #build!, #ship! and #scrap!" do
98
97
  w1 = Workstation.new(:place)
@@ -103,37 +102,212 @@ describe "Workstation" do
103
102
  w1.cycle
104
103
  end
105
104
 
105
+ describe "the #before method" do
106
+ it "should empty @answers"
107
+ end
108
+
109
+ describe "the #after method" do
110
+ it "should save everything in @answers to the persistent store"
111
+ end
106
112
 
107
113
  describe "#receive!" do
108
- it "should access its persistent store"
109
- it "should gather its 'current' work_in_process into self#answers"
110
- it "should gather its 'current' collaborators' work_in_process into self#collaborator_answers"
114
+ # the superclass we're testing (Workstation) should do nothing here,
115
+ # but there are some helper methods defined for use in subclasses;
116
+ # we should test those
117
+
118
+ describe "gather_mine" do
119
+ before(:each) do
120
+ @w1 = Workstation.new(:ws1, factory_name:"this_factory")
121
+ @uri = "http://127.0.0.1:5984/this_factory"
122
+ @design_doc = "ws1/current" # we'll assume this has been set up!
123
+ @view_uri = "http://127.0.0.1:5984/this_factory/_design/ws1/_view/current"
124
+ FakeWeb.allow_net_connect = false
125
+ @canned = '{"total_rows":1,"offset":0,"rows":[{"id":"0f60c293ad736abfdb083d33f71ef9ab","key":"ws1","value":{"_id":"0f60c293ad736abfdb083d33f71ef9ab","_rev":"1-473467b6dc1a4cba3498dd6eeb8e3206","blueprint":"do bar","tags":[],"scores":{"badness": 12.345},"progress":12,"timestamp":"2010/04/14 17:09:14 +0000"}}]}'
126
+ end
127
+
128
+ it "should use the Batch#load_from_couch method" do
129
+ FakeWeb.register_uri(:any, @view_uri, :body => @canned, :status => [200, "OK"])
130
+ Batch.should_receive(:load_from_couch).with(@uri,@design_doc).and_return(Batch.new)
131
+ @w1.gather_mine
132
+ end
133
+
134
+ it "should add that Batch into self#answers" do
135
+ FakeWeb.register_uri(:any, @view_uri, :body => @canned, :status => [200, "OK"])
136
+ @w1.answers.length.should == 0
137
+ @w1.gather_mine
138
+ @w1.answers.length.should == 1
139
+ @w1.answers[0].scores[:badness].should == 12.345
140
+ end
141
+ end
142
+
143
+
144
+ describe "gather_into" do
145
+ end
111
146
  end
112
147
 
113
148
 
114
149
  describe "#build!" do
150
+ # the superclass we're testing (Workstation) should do nothing here,
151
+ # but there are some helper methods defined for use in subclasses;
152
+ # we should test those
115
153
 
154
+ describe "process_with" do
155
+ before(:each) do
156
+ @w1 = Workstation.new(:pity_foo)
157
+ @w1.answers = Batch[Answer.new("block{}")]
158
+ @sampler = AnyOneSampler.new
159
+ end
160
+
161
+ it "should accept one parameter" do
162
+ @w1.method(:process_with).arity.should == 1
163
+ end
164
+
165
+ it "should only accept a search operator" do
166
+ lambda{@w1.process_with(8)}.should raise_error(ArgumentError)
167
+ lambda{@w1.process_with(AnyOneSampler.new)}.should_not raise_error
168
+ end
169
+
170
+ it "should call the search operator's '#generate" do
171
+ @sampler.should_receive(:generate)
172
+ @w1.process_with(@sampler)
173
+ end
174
+
175
+ it "should pass in self#answers to the call to #generate" do
176
+ @sampler.should_receive(:generate).with(@w1.answers)
177
+ @w1.process_with(@sampler)
178
+ end
179
+
180
+ it "should return a Batch" do
181
+ @w1.process_with(@sampler).should be_a_kind_of(Batch)
182
+ end
183
+ end
116
184
  end
117
185
 
118
186
 
119
187
  describe "#ship!" do
120
- it "should be an Array of stored procedures"
121
- it "should always include (as a last entry) a Proc that returns 'false'"
122
- it "should call all the Procs in order, for every member of its population"
123
- it "should select a random downstream destination if none is specified by the rule"
124
- it "should fail silently if there are no downstream stations"
125
- it "should call every rule, in turn, sending every Answer off before moving on"
188
+ # the superclass we're testing (Workstation) should do nothing here,
189
+ # but there are some helper methods defined for use in subclasses;
190
+ # we should test those
191
+
192
+ describe "ship_to" do
193
+ before(:each) do
194
+ @w2 = Workstation.new(:lulu)
195
+ @a1 = Answer.new("do fun_stuff", tags:[:lulu])
196
+ @a2 = Answer.new("do sad_stuff", tags:[:lulu])
197
+ @w2.answers = Batch[@a1,@a2]
198
+ end
199
+
200
+ it "should accept a single argument" do
201
+ @w2.method(:ship_to).arity.should == 1
202
+ end
203
+
204
+ it "should check the argument is a symbol" do
205
+ lambda{@w2.ship_to(8)}.should raise_error(ArgumentError)
206
+ lambda{@w2.ship_to(:heaven)}.should_not raise_error
207
+ end
208
+
209
+ it "should pass every element of @answers into the associated block" do
210
+ Math.should_receive(:sin).exactly(2).times
211
+ @w2.ship_to(:heaven) {|a| Math.sin(12.0)}
212
+ end
213
+
214
+ it "should add a new location tag to the answers in the filtered subset" do
215
+ @a1.should_receive(:add_tag).with(:xyzzy)
216
+ @a2.should_receive(:add_tag).with(:xyzzy)
217
+ @w2.ship_to(:xyzzy) {|a| true}
218
+ end
219
+
220
+ it "should remove the old location tag to the answers in the filtered subset" do
221
+ @a1.should_receive(:remove_tag).with(:lulu)
222
+ @a2.should_receive(:remove_tag).with(:lulu)
223
+ @w2.ship_to(:xyzzy) {|a| true}
224
+ end
225
+
226
+ it "should not touch the tags of answers not in the filtered subset" do
227
+ @a1.should_receive(:remove_tag).with(:lulu)
228
+ @a2.should_not_receive(:remove_tag)
229
+ @w2.ship_to(:xyzzy) {|a| a.blueprint.include? "fun"}
230
+ end
231
+ end
126
232
  end
127
233
 
128
234
 
129
235
  describe "scrap!" do
130
- it "should be an Array of stored procedures"
131
- it "should return 'true' to indicate that a particular Answer should be scrapped"
132
- it "should use an Array of stored procedures"
133
- it "should return a single boolean to indicate that scrapping should continue"
134
- it "should always include (as a last entry) a Proc that checks whether population > capacity"
135
- it "should set the workstation of scrapped Answers to Scrapyard"
136
- it "should call rules in order, scrapping all indicated Answers, until scrap_trigger? is false"
236
+
237
+ # the superclass we're testing (Workstation) should do nothing here,
238
+ # but there are some helper methods defined for use in subclasses;
239
+ # we should test those
240
+
241
+ describe "scrap_if" do
242
+ before(:each) do
243
+ @w3 = Workstation.new(:falafel)
244
+ @a1 = Answer.new("do fun_stuff", progress:1, tags:[:falafel])
245
+ @a2 = Answer.new("do sad_stuff", progress:99, tags:[:falafel])
246
+ @w3.answers = Batch[@a1,@a2]
247
+ end
248
+
249
+ it "should accept a single argument" do
250
+ @w3.method(:scrap_if).arity.should == 1
251
+ end
252
+
253
+ it "should pass every element of @answers into a block" do
254
+ Math.should_receive(:cos).exactly(2).times
255
+ @w3.scrap_if("Math says so") {|a| Math.cos(12.0)}
256
+ end
257
+
258
+ it "should add a new location tag :SCRAP to the answers in the filtered subset" do
259
+ @a1.should_receive(:add_tag).with(:SCRAP)
260
+ @a2.should_receive(:add_tag).with(:SCRAP)
261
+ @w3.scrap_if("everything dies") {|a| true}
262
+ end
263
+
264
+ it "should remove the old location tag to the answers in the filtered subset" do
265
+ @a1.should_receive(:remove_tag).with(:falafel)
266
+ @a2.should_receive(:remove_tag).with(:falafel)
267
+ @w3.scrap_if("entropy") {|a| true}
268
+ end
269
+
270
+ it "should not touch the tags of answers not in the filtered subset" do
271
+ @a1.should_receive(:remove_tag).with(:falafel)
272
+ @a2.should_not_receive(:remove_tag)
273
+ @w3.scrap_if("insufficient progress") {|a| a.progress < 10}
274
+ end
275
+ end
276
+
277
+ describe "scrap_everything" do
278
+ before(:each) do
279
+ @w4 = Workstation.new(:ice_station_zebra)
280
+ @a1 = Answer.new("do anything", tags:[:ice_station_zebra])
281
+ @a2 = Answer.new("do whatevz", tags:[:ice_station_zebra])
282
+ @w4.answers = Batch[@a1,@a2]
283
+ end
284
+
285
+ it "should have arity 0" do
286
+ @w4.method(:scrap_everything).arity.should == 0
287
+ end
288
+
289
+ it "should call scrap_if" do
290
+ @w4.should_receive(:scrap_if)
291
+ @w4.scrap_everything
292
+ end
293
+
294
+ it "should send every answer to :SCRAP" do
295
+ @w4.answers.each {|a| a.tags.should_not include(:SCRAP)}
296
+ @w4.scrap_everything
297
+ @w4.answers.each {|a| a.tags.should include(:SCRAP)}
298
+ end
299
+
300
+ it "should remove the current location from every answer" do
301
+ @w4.answers.each {|a| a.tags.should include(:ice_station_zebra)}
302
+ @w4.scrap_everything
303
+ @w4.answers.each {|a| a.tags.should_not include(:ice_station_zebra)}
304
+ end
305
+
306
+ it "should be safe to repeat the statement" do
307
+ @w4.scrap_everything
308
+ lambda{@w4.scrap_everything}.should_not raise_error
309
+ end
310
+ end
137
311
  end
138
312
  end
139
313
  end
@@ -11,7 +11,7 @@ describe ProgramPointEvaluator do
11
11
 
12
12
  describe "#evaluate" do
13
13
  before(:each) do
14
- @ppe = ProgramPointEvaluator.new(:name => :point_count)
14
+ @ppe = ProgramPointEvaluator.new(:score_label => :point_count)
15
15
  @dudes = Batch[
16
16
  Answer.new("block {}"),
17
17
  Answer.new("block { block {}}"),
@@ -39,7 +39,7 @@ describe TestCaseEvaluator do
39
39
  describe "initialize" do
40
40
  it "should have a name" do
41
41
  lambda{TestCaseEvaluator.new()}.should raise_error(ArgumentError)
42
- lambda{TestCaseEvaluator.new(name:"boolean_multiplexer_SSE")}.should_not raise_error
42
+ lambda{TestCaseEvaluator.new(score_label:"boolean_multiplexer_SSE")}.should_not raise_error
43
43
  end
44
44
 
45
45
  it "should have all the info it needs to set up an Interpreter"
@@ -47,7 +47,7 @@ describe TestCaseEvaluator do
47
47
 
48
48
  describe "evaluate" do
49
49
  before(:each) do
50
- @tce = TestCaseEvaluator.new(:name => :error)
50
+ @tce = TestCaseEvaluator.new(:score_label => :error)
51
51
  @dudes = Batch[
52
52
  Answer.new("value «int»\n«int» 12"),
53
53
  Answer.new("value «int»\n«int» -9912"),
@@ -6,7 +6,7 @@ describe "nondominated_subset operator" do
6
6
  @myNondominatedScreener = NondominatedSubsetSelector.new
7
7
  @params = {points:3, instruction_names:[:int_add, :int_multiply], type_names:["int"]}
8
8
  @myGuesser = RandomGuessOperator.new(@params)
9
- @twoGuys = @myGuesser.generate(2)
9
+ @twoGuys = @myGuesser.generate(Batch.new,how_many:2)
10
10
  end
11
11
 
12
12
  it "should be a kind of SearchOperator" do
@@ -20,7 +20,7 @@ describe "nondominated_subset operator" do
20
20
  end
21
21
 
22
22
  it "the #all_shared_scores method should return an Array of the keys of the #scores hashes in the crowd" do
23
- twoGuys = @myGuesser.generate(2)
23
+ twoGuys = @myGuesser.generate(Batch.new,how_many:2)
24
24
  twoGuys[0].scores = {x2:612, x1:77, x3:712}
25
25
  twoGuys[1].scores = {x2:2, x1:3, x3:4}
26
26
  @myNondominatedScreener.all_shared_scores(twoGuys).sort.should == [:x1,:x2, :x3].sort
@@ -31,7 +31,7 @@ describe "nondominated_subset operator" do
31
31
  end
32
32
 
33
33
  it "should produce a Batch of Answer objects when it receives #generate; at least one" do
34
- twoGuys = @myGuesser.generate(2)
34
+ twoGuys = @myGuesser.generate(Batch.new,how_many:2)
35
35
  twoGuys[0].scores = {:x2 => 612, :x1 => 77, :x3 => 712}
36
36
  twoGuys[1].scores = {:x2 => 2, :x1 => 3, :x3 => 4}
37
37
  @myNondominatedScreener.generate(twoGuys).should be_a_kind_of(Batch)
@@ -39,7 +39,7 @@ describe "nondominated_subset operator" do
39
39
  end
40
40
 
41
41
  it "should work, passing along references not clones to the original guys" do
42
- twoGuys = @myGuesser.generate(2)
42
+ twoGuys = @myGuesser.generate(Batch.new,how_many:2)
43
43
  twoGuys[0].scores = {x2:612, x1:77, x3:712}
44
44
  twoGuys[1].scores = {x2:2, x1:3, x3:4}
45
45
  @myNondominatedScreener.generate(twoGuys).should include(twoGuys[1])
@@ -54,7 +54,7 @@ describe "nondominated_subset operator" do
54
54
  end
55
55
 
56
56
  it "should work the same no matter what the scores hash order" do
57
- twoGuys = @myGuesser.generate(2)
57
+ twoGuys = @myGuesser.generate(Batch.new,how_many:2)
58
58
  twoGuys[0].scores = {:x1 => 77, :x3 => 712,:x2 => 612}
59
59
  twoGuys[1].scores = {:x2 => 2, :x1 => 3, :x3 => 4}
60
60
  @myNondominatedScreener.generate(twoGuys).should include(twoGuys[1])
@@ -62,7 +62,7 @@ describe "nondominated_subset operator" do
62
62
  end
63
63
 
64
64
  it "can use the 'template' parameter to compare individuals by a specified vector of scores" do
65
- threeGuys = @myGuesser.generate(3)
65
+ threeGuys = @myGuesser.generate(Batch.new,how_many:3)
66
66
  threeGuys[0].scores = {:x1 => 1, :x2 => 2, :x3 => 3}
67
67
  threeGuys[1].scores = {:x1 => 2, :x2 => 1, :x3 => 1}
68
68
  threeGuys[2].scores = {:x1 => 4, :x2 => 0, :x3 => 2}
@@ -83,7 +83,7 @@ describe "nondominated_subset operator" do
83
83
 
84
84
 
85
85
  it "should use a default 'template' parameter that's the intersection of scores keys in the crowd" do
86
- twoGuys = @myGuesser.generate(2)
86
+ twoGuys = @myGuesser.generate(Batch.new,how_many:2)
87
87
  twoGuys[0].scores = {x1:1, x2:2, x3:3}
88
88
  twoGuys[1].scores = { x2:0, x4:12}
89
89
 
@@ -93,7 +93,7 @@ describe "nondominated_subset operator" do
93
93
  end
94
94
 
95
95
  it "should return Answers that belonged to crowd passed in" do
96
- twoGuys = @myGuesser.generate(2)
96
+ twoGuys = @myGuesser.generate(Batch.new,how_many:2)
97
97
  orig_IDs = twoGuys.collect {|dude| dude.object_id}
98
98
  twoGuys[0].scores = {:x1 => 1, :x2 => 2, :x3 => 3}
99
99
  twoGuys[1].scores = { :x2 => 1, :x4 => 3}
@@ -18,9 +18,8 @@ describe "random_guess operator" do
18
18
  thisGuesser.incoming_options[:foo].should == 99
19
19
  end
20
20
 
21
-
22
21
  it "should produce a Batch of Answers when it receives #generate" do
23
- newDudes = @myGuesser.generate
22
+ newDudes = @myGuesser.generate(Batch.new)
24
23
  newDudes.should be_a_kind_of(Batch)
25
24
  newDudes[0].should be_a_kind_of(Answer)
26
25
  newDudes[0].blueprint.should_not == nil
@@ -28,12 +27,12 @@ describe "random_guess operator" do
28
27
  end
29
28
 
30
29
  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
30
+ @myGuesser.generate(Batch.new).length.should == 1
31
+ @myGuesser.generate(Batch.new,how_many:4).length.should == 4
33
32
  end
34
33
 
35
34
  it "should have a parsed blueprint as its #program attribute" do
36
- newDudes = @myGuesser.generate
35
+ newDudes = @myGuesser.generate(Batch.new)
37
36
  newDudes[0].program.should be_a_kind_of(NudgeProgram)
38
37
  end
39
38
 
@@ -44,31 +43,37 @@ describe "random_guess operator" do
44
43
  reference_names: ["x1", "x2", "x3"])
45
44
 
46
45
  lambda{@myNewGuesser.generate(
47
- 3,
46
+ Batch.new,
47
+ how_many:3,
48
48
  target_size_in_points: 12,
49
49
  reference_names: ["y1"])}.should_not raise_error
50
50
 
51
51
  @myNewGuesser.generate(
52
- 3,
52
+ Batch.new,
53
+ how_many:3,
53
54
  target_size_in_points: 12)[0].program.points.should_not == 7
54
55
 
55
56
  @myNewGuesser.generate(
56
- 3,
57
+ Batch.new,
58
+ how_many:3,
57
59
  target_size_in_points: 12)[0].program.points.should == 12
58
60
 
59
61
  @myNewGuesser.generate(
60
- 1,
62
+ Batch.new,
63
+ how_many:1,
61
64
  target_size_in_points: 16,
62
65
  probabilities:{b:0,r:1,v:0,i:0},
63
66
  reference_names: ["y1"])[0].blueprint.should include("y1")
64
67
  end
65
68
 
66
69
  it "should produce a Batch that contains Answers with progress=0 only" do
67
- @myGuesser.generate(12).each {|dude| dude.progress.should == 0}
70
+ @myGuesser.generate(Batch.new,how_many:12).each {|dude| dude.progress.should == 0}
68
71
  end
69
72
 
70
73
  it "should handle generated footnotes correctly" do
71
- @myGuesser.generate(1,
74
+ @myGuesser.generate(
75
+ Batch.new,
76
+ how_many:1,
72
77
  target_size_in_points: 52,
73
78
  type_names:["int"],
74
79
  probabilities: {b:0,v:1,i:0,r:0})[0].program.footnote_section.scan(/«int»/).length.should == 51
@@ -12,7 +12,7 @@ describe "resample_and_clone operator" do
12
12
  end
13
13
 
14
14
  it "should produce a list of Answers when it receives #generate" do
15
- newDudes = @mySampler.generate(@myGuesser.generate(3))
15
+ newDudes = @mySampler.generate(@myGuesser.generate(Batch.new,how_many:3))
16
16
  newDudes.should be_a_kind_of(Batch)
17
17
  newDudes[0].should be_a_kind_of(Answer)
18
18
  newDudes[0].blueprint.should_not == nil
@@ -20,35 +20,35 @@ describe "resample_and_clone operator" do
20
20
  end
21
21
 
22
22
  it "should produce one Answer with a blueprint identical to one of the passed in crowd's" do
23
- pop = @myGuesser.generate(1)
23
+ pop = @myGuesser.generate(Batch.new,how_many:1)
24
24
  newDudes = @mySampler.generate(pop)
25
25
  newDudes[0].blueprint.should == pop[0].blueprint
26
26
  end
27
27
 
28
28
  it "should return more than one individual when asked to, resampling as needed" do
29
- newDudes = @mySampler.generate(@myGuesser.generate(10))
29
+ newDudes = @mySampler.generate(@myGuesser.generate(Batch.new,how_many:10))
30
30
  newDudes.length.should == 1
31
- newDudes = @mySampler.generate(@myGuesser.generate(3),2)
31
+ newDudes = @mySampler.generate(@myGuesser.generate(Batch.new,how_many:3),2)
32
32
  newDudes.length.should == 2
33
- newDudes = @mySampler.generate(@myGuesser.generate(1),2)
33
+ newDudes = @mySampler.generate(@myGuesser.generate(Batch.new,how_many:1),2)
34
34
  newDudes.length.should == 2
35
35
  newDudes[0].blueprint.should == newDudes[1].blueprint
36
36
  end
37
37
 
38
38
  it "should not return links to the original program copies in the new clones" do
39
- pop = @myGuesser.generate(3)
39
+ pop = @myGuesser.generate(Batch.new,how_many:3)
40
40
  newDudes = @mySampler.generate(pop)
41
41
  pop.collect {|old_dude| old_dude.program.object_id}.should_not include(newDudes[0].program.object_id)
42
42
  end
43
43
 
44
44
  it "should have a parsed blueprint as its #program attribute" do
45
- pop = @myGuesser.generate(3)
45
+ pop = @myGuesser.generate(Batch.new,how_many:3)
46
46
  newDudes = @mySampler.generate(pop)
47
47
  newDudes[0].program.should be_a_kind_of(NudgeProgram)
48
48
  end
49
49
 
50
50
  it "should increment the #progress of each clone" do
51
- pop = @myGuesser.generate(3)
51
+ pop = @myGuesser.generate(Batch.new,how_many:3)
52
52
  pop.each {|donor| donor.stub(:progress).and_return(12)}
53
53
  newDudes = @mySampler.generate(pop)
54
54
  newDudes.each {|kid| kid.progress.should == 13}