answer-factory 0.1.3.4 → 0.1.3.5

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/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.3.4
1
+ 0.1.3.5
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{answer-factory}
8
- s.version = "0.1.3.4"
8
+ s.version = "0.1.3.5"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Bill Tozier", "Trek Glowacki", "Jesse Sielaff"]
12
- s.date = %q{2010-05-27}
12
+ s.date = %q{2010-06-02}
13
13
  s.default_executable = %q{answer-factory}
14
14
  s.description = %q{The pragmaticgp gem provides a simple framework for building, running and managing genetic programming experiments which automatically discover algorithms and equations to solve user-defined problems.}
15
15
  s.email = %q{bill@vagueinnovation.com}
@@ -36,6 +36,7 @@ Gem::Specification.new do |s|
36
36
  "lib/machines/evaluate_simple_score.rb",
37
37
  "lib/machines/evaluate_with_test_cases.rb",
38
38
  "lib/machines/infrastructure.rb",
39
+ "lib/machines/mutate_codeblock.rb",
39
40
  "lib/machines/mutate_footnotes.rb",
40
41
  "lib/machines/select_by_summed_rank.rb",
41
42
  "lib/machines/select_nondominated.rb",
@@ -51,6 +52,7 @@ Gem::Specification.new do |s|
51
52
  "spec/machines/evaluate_simple_score_spec.rb",
52
53
  "spec/machines/evaluate_with_test_cases_spec.rb",
53
54
  "spec/machines/infrastructure_spec.rb",
55
+ "spec/machines/mutate_codeblock_spec.rb",
54
56
  "spec/machines/mutate_footnotes_spec.rb",
55
57
  "spec/machines/select_by_summed_rank_spec.rb",
56
58
  "spec/machines/select_nondominated_spec.rb",
@@ -75,6 +77,7 @@ Gem::Specification.new do |s|
75
77
  "spec/machines/evaluate_simple_score_spec.rb",
76
78
  "spec/machines/evaluate_with_test_cases_spec.rb",
77
79
  "spec/machines/infrastructure_spec.rb",
80
+ "spec/machines/mutate_codeblock_spec.rb",
78
81
  "spec/machines/mutate_footnotes_spec.rb",
79
82
  "spec/machines/select_by_summed_rank_spec.rb",
80
83
  "spec/machines/select_nondominated_spec.rb",
@@ -16,10 +16,12 @@ require 'machines/evaluate_simple_score'
16
16
  require 'machines/evaluate_with_test_cases'
17
17
  require 'machines/select_nondominated'
18
18
  require 'machines/select_by_summed_rank'
19
+ require 'machines/mutate_codeblock'
19
20
  require 'machines/mutate_footnotes'
20
21
 
21
22
 
22
23
 
24
+
23
25
  require 'factories/factory'
24
26
  require 'factories/workstation'
25
27
 
@@ -113,6 +113,7 @@ module AnswerFactory
113
113
  end
114
114
  end
115
115
 
116
+
116
117
  def move_to(where)
117
118
  raise ArgumentError, "#{where} is not a Symbol" unless where.kind_of?(Symbol)
118
119
  @location = where.to_sym
@@ -14,15 +14,13 @@ module AnswerFactory
14
14
  @name = options[:name] || "evaluator"
15
15
  @sensors = options[:sensors] || {}
16
16
  @csv_filename = options[:training_data_csv]
17
-
18
- self.load_training_data!
19
17
  end
20
18
 
21
19
 
22
20
  def score(batch, overridden_options = {})
23
21
  all_options = @options.merge(overridden_options)
24
- name = all_options[:name]
25
22
 
23
+ score_name = all_options[:name]
26
24
 
27
25
  raise ArgumentError, "EvaluateWithTestCases#score cannot process a #{batch.class}" unless
28
26
  batch.kind_of?(Batch)
@@ -33,6 +31,7 @@ module AnswerFactory
33
31
 
34
32
  batch.each do |answer|
35
33
 
34
+
36
35
  raw_results = Hash.new {|hash, key| hash[key] = []}
37
36
 
38
37
  @test_cases.each do |t|
@@ -54,13 +53,12 @@ module AnswerFactory
54
53
  end
55
54
 
56
55
  @sensors.each do |sensor_name, sensor_block|
57
- answer.scores[sensor_name] = raw_results[sensor_name].inject(0) do |sum, measurement|
58
- sum + measurement.abs
59
- end
56
+ answer.scores["#{score_name}_#{sensor_name}".to_sym] =
57
+ raw_results[sensor_name].inject(0) do |sum, measurement|
58
+ sum + measurement.abs
59
+ end
60
60
  end
61
61
  end
62
-
63
-
64
62
  return batch
65
63
  end
66
64
 
@@ -87,24 +85,28 @@ module AnswerFactory
87
85
  end
88
86
 
89
87
 
88
+ def save_view_doc!
89
+ db = CouchRest.database!(training_datasource)
90
+ db.save_doc({'_id' => "_design/#{@name}",
91
+ views: { test_cases: { map: "function(doc) { emit(doc._id, doc); }"}}})
92
+ end
93
+
94
+
90
95
  def install_training_data_from_csv(csv_filename = @csv_filename)
91
- reader = CSV.new(File.open(csv_filename), headers: true)
92
- reader.readline
93
- split_point = reader.headers.find_index(nil)
94
96
 
95
- input_headers = reader.headers[0...split_point].collect {|head| header_prep(head)}
96
- output_headers = reader.headers[split_point+1..-1].collect {|head| head.strip}
97
+ reader = CSV.new(File.open(csv_filename), headers: true)
98
+ headers = csv_headers(reader)
97
99
 
98
- reader.rewind
100
+ save_view_doc!
99
101
 
100
- offset = input_headers.length+1
102
+ offset = headers[:input_headers].length+1
101
103
  db = CouchRest.database!(training_datasource)
102
104
 
103
105
  reader.each do |row|
104
106
  inputs = {}
105
- input_headers.each_with_index {|header,i| inputs[header] = row[i].strip}
107
+ headers[:input_headers].each_with_index {|header,i| inputs[header] = row[i].strip}
106
108
  outputs = {}
107
- output_headers.each_with_index {|header,i| outputs[header] = row[i+offset].strip}
109
+ headers[:output_headers].each_with_index {|header,i| outputs[header] = row[i+offset].strip}
108
110
  db.bulk_save_doc( {:inputs => inputs, :outputs => outputs})
109
111
  end
110
112
 
@@ -113,6 +115,16 @@ module AnswerFactory
113
115
  end
114
116
 
115
117
 
118
+ def csv_headers(csv_reader)
119
+ csv_reader.readline
120
+ split_point = csv_reader.headers.find_index(nil)
121
+ input_headers = csv_reader.headers[0...split_point].collect {|head| header_prep(head)}
122
+ output_headers = csv_reader.headers[split_point+1..-1].collect {|head| head.strip}
123
+ csv_reader.rewind
124
+ return {input_headers:input_headers, output_headers:output_headers}
125
+ end
126
+
127
+
116
128
  def load_training_data!
117
129
  db = CouchRest.database!(training_datasource)
118
130
  result = db.view("#{@name}/test_cases")
@@ -0,0 +1,42 @@
1
+ #encoding: utf-8
2
+ module AnswerFactory
3
+ module Machines
4
+
5
+
6
+
7
+
8
+ class MutateCodeblock < Machine
9
+
10
+ def build(batch, overridden_options={})
11
+ raise ArgumentError, "MutateCodeblock#build cannot process a #{batch.class}" unless
12
+ batch.kind_of?(Batch)
13
+
14
+ all_options = @options.merge(overridden_options)
15
+
16
+ replicates = all_options[:replicates] || 1
17
+
18
+ result = Batch.new
19
+
20
+ batch.each do |answer|
21
+ replicates.times do
22
+ which_point = rand(answer.points) + 1
23
+ size = all_options[:size_preserving?] ?
24
+ answer.program[which_point].points :
25
+ Kernel.rand(2 * answer.program[which_point].points) + 1
26
+ new_code = NudgeType::CodeType.any_value(all_options.merge({target_size_in_points:size}))
27
+ mutated_code = answer.replace_point_or_clone(which_point, new_code)
28
+ variant = Answer.new(mutated_code, progress:answer.progress + 1)
29
+ result << variant
30
+ end
31
+ end
32
+
33
+ return result
34
+ end
35
+
36
+
37
+ alias :generate :build
38
+
39
+
40
+ end
41
+ end
42
+ end
@@ -42,18 +42,19 @@ describe "CouchDB stuff" do
42
42
 
43
43
  describe "Machine CouchDB interaction" do
44
44
  before(:each) do
45
- the_database_name = "#{@db_uri}_training"
46
- @db = CouchRest.database!(the_database_name)
45
+ @db_uri = "#{configatron.factory.couchdb.server}/#{configatron.factory.couchdb.name}"
46
+ training_database_name = "#{@db_uri}_training"
47
+ @db = CouchRest.database!(training_database_name)
47
48
  end
48
49
 
49
- it "should accept :install_training_data_from_csv to populate a db from csv" do
50
+ after(:each) do
51
+ @db.delete!
52
+ end
53
+
54
+
55
+ it "should populate the training db from a csv upon :install_training_data_from_csv" do
50
56
  configatron.temp do
51
57
  configatron.factory.training_datasource = "http://127.0.0.1:5984/integration_test_db_training"
52
- @db.save_doc(
53
- {'_id' => "_design/tester",
54
- views: { test_cases: { map:
55
- "function(doc) { emit(doc._id, doc); }"}}})
56
-
57
58
  @my_machine = Machines::EvaluateWithTestCases.new(name: :tester)
58
59
  @my_machine.install_training_data_from_csv('./spec/fixtures/my_data_source.csv')
59
60
  saved = @db.documents
@@ -79,6 +80,7 @@ describe "CouchDB stuff" do
79
80
  configatron.temp do
80
81
  configatron.factory.training_datasource = "http://127.0.0.1:5984/integration_test_db_training"
81
82
  @my_machine = Machines::EvaluateWithTestCases.new(name: :tester)
83
+ @my_machine.install_training_data_from_csv('./spec/fixtures/my_data_source.csv')
82
84
  @my_machine.load_training_data!
83
85
  @my_machine.test_cases[0].inputs["x1:int"].should == "3"
84
86
  end
@@ -56,7 +56,7 @@ describe "EvaluateWithTestCases" do
56
56
 
57
57
  describe "initialization" do
58
58
 
59
- describe "name" do
59
+ describe "machine name" do
60
60
  it "should have a name" do
61
61
  @tester.should respond_to(:name)
62
62
  end
@@ -127,7 +127,7 @@ describe "EvaluateWithTestCases" do
127
127
  it "should register all the sensors" do
128
128
  @tester.sensors = {"y1" => Proc.new{|interpreter| interpreter.peek_value(:int)} }
129
129
  i = Interpreter.new
130
- Interpreter.should_receive(:new).and_return(i)
130
+ Interpreter.stub(:new).and_return(i)
131
131
  i.should_receive(:register_sensor).exactly(1).times
132
132
  @tester.score(@batch)
133
133
  end
@@ -138,11 +138,9 @@ describe "EvaluateWithTestCases" do
138
138
  "do a", {:name=>:tester, :target_size_in_points=>99}).and_return(i)
139
139
  @tester.score(@batch,target_size_in_points:99)
140
140
  end
141
-
142
-
143
-
144
141
  end
145
142
 
143
+
146
144
  describe "install_training_data_from_csv!" do
147
145
  before(:each) do
148
146
  FakeWeb.register_uri(:any,
@@ -152,10 +150,15 @@ describe "EvaluateWithTestCases" do
152
150
  "http://127.0.0.1:5984/dammit_training/_design/tester/_view/test_cases",
153
151
  :body => @canned, :status => [200, "OK"])
154
152
 
153
+
154
+
155
155
  @f1 = Factory.new(name: "dammit")
156
156
  @my_csv = "./spec/fixtures/my_data_source.csv"
157
157
  @m1 = EvaluateWithTestCases.new(name: :tester, training_data_csv: @my_csv)
158
158
  @training_db = "http://127.0.0.1:5984/dammit_training"
159
+ @my_view = {'_id' => "_design/tester",
160
+ views: { test_cases: { map:
161
+ "function(doc) { emit(doc._id, doc); }"}}}
159
162
 
160
163
  end
161
164
 
@@ -166,22 +169,25 @@ describe "EvaluateWithTestCases" do
166
169
  end
167
170
 
168
171
  it "should open a csv file" do
172
+ @m1.stub(:save_view_doc!) # we're just checking the file is touched
169
173
  f = File.open(@my_csv)
170
- File.should_receive(:open).and_return(f)
174
+ File.stub(:open).and_return(f)
171
175
  c = CSV.new(f, headers: true)
172
- CSV.should_receive(:new).with(f, headers: true).and_return(c)
176
+ CSV.stub(:new).with(f, headers: true).and_return(c)
173
177
  @m1.install_training_data_from_csv(@my_csv)
174
178
  end
175
179
 
176
180
  it "should be the training_data default db" do
181
+ @m1.stub(:save_view_doc!) # we're just checking the filename
177
182
  db = CouchRest.database!(@training_db)
178
- CouchRest.should_receive(:database!).with(@training_db).and_return(db)
183
+ CouchRest.stub(:database!).with(@training_db).and_return(db)
179
184
  @m1.install_training_data_from_csv(@my_csv)
180
185
  end
181
186
 
182
187
  it "makes one doc for every row" do
188
+ @m1.stub(:save_view_doc!) # we're just checking data row saving
183
189
  db = CouchRest.database!(@training_db)
184
- CouchRest.should_receive(:database!).with(@training_db).and_return(db)
190
+ CouchRest.stub(:database!).with(@training_db).and_return(db)
185
191
  db.should_receive(:bulk_save_doc).exactly(3).times
186
192
  @m1.install_training_data_from_csv(@my_csv)
187
193
  end
@@ -194,8 +200,18 @@ describe "EvaluateWithTestCases" do
194
200
  lambda{@m1.header_prep(":int")}.should raise_error ArgumentError
195
201
  end
196
202
 
203
+ it "should create the appropriate view document" do
204
+ db = CouchRest.database!(@training_db)
205
+ CouchRest.stub(:database!).with(@training_db).and_return(db)
206
+ db.stub(:bulk_save_doc)
207
+ db.should_receive(:save_doc).exactly(1).times.with(@my_view)
208
+ @m1.install_training_data_from_csv(@my_csv)
209
+ end
210
+
197
211
  end
198
212
 
213
+
214
+
199
215
  describe "load_training_data!" do
200
216
 
201
217
  before(:each) do
@@ -220,7 +236,7 @@ describe "EvaluateWithTestCases" do
220
236
  "http://127.0.0.1:5984/dammit_training/_design/tester/_view/test_cases",
221
237
  :body => @canned, :status => [200, "OK"])
222
238
  db = CouchRest.database!(@m1.training_datasource)
223
- CouchRest.should_receive(:database!).and_return(db)
239
+ CouchRest.stub(:database!).and_return(db)
224
240
  db.should_receive(:view).with(@design_doc).and_return(@expected)
225
241
  @m1.load_training_data!
226
242
  end
@@ -229,14 +245,14 @@ describe "EvaluateWithTestCases" do
229
245
 
230
246
  it "should ask for the view document" do
231
247
  db = CouchRest.database!(@m1.training_datasource)
232
- CouchRest.should_receive(:database!).and_return(db)
248
+ CouchRest.stub(:database!).and_return(db)
233
249
  db.should_receive(:view).with(@design_doc).and_return(@expected)
234
250
  @m1.load_training_data!
235
251
  end
236
252
 
237
253
  it "should store Array of TestCases in @test_cases" do
238
254
  db = CouchRest.database!(@m1.training_datasource)
239
- CouchRest.should_receive(:database!).and_return(db)
255
+ CouchRest.stub(:database!).and_return(db)
240
256
  db.should_receive(:view).with(@design_doc).and_return(@expected)
241
257
 
242
258
  @m1.load_training_data!
@@ -245,6 +261,7 @@ describe "EvaluateWithTestCases" do
245
261
  end
246
262
  end
247
263
 
264
+
248
265
  describe "scoring" do
249
266
  before(:each) do
250
267
  @m1 = EvaluateWithTestCases.new(name: :tester)
@@ -266,28 +283,35 @@ describe "EvaluateWithTestCases" do
266
283
 
267
284
  it "should run all the Interpreters" do
268
285
  @m1.stub!(:load_training_data!)
269
- Interpreter.should_receive(:new).exactly(10).times.and_return(@i1)
286
+ Interpreter.stub(:new).exactly(10).times.and_return(@i1)
270
287
  @i1.should_receive(:run).at_least(1).times.and_return({})
271
288
  @m1.score(@batch)
272
289
  end
273
290
 
274
291
  it "should register its sensors before each Interpreter run" do
275
- Interpreter.stub!(:new).and_return(@i1)
292
+ Interpreter.stub(:new).and_return(@i1)
276
293
  @i1.should_receive(:register_sensor).at_least(1).times
277
294
  @m1.score(@batch)
278
295
  end
279
296
 
280
297
  it "should have a score for each sensor" do
281
298
  @m1.score(@batch)
282
- @batch.first.scores["y1"].should_not == nil
283
- @batch.first.scores["y2"].should_not == nil
299
+ @batch.first.scores[:tester_y1].should_not == nil
300
+ @batch.first.scores[:tester_y2].should_not == nil
301
+ end
302
+
303
+ it "should not re-evaluate an Answer's score if :static is true and the score is set" do
304
+ pending
305
+ @m1.score(@batch)
306
+ Interpreter.should_not_receive(:new)
307
+ @m1.score(@batch, static:true)
284
308
  end
285
309
 
286
310
  it "should return sum of absolute errors" do
287
311
  @m1.stub!(:load_training_data!)
288
312
  @m1.score(@batch)
289
- @batch[0].scores["y1"].should == 777+775+773+771+769+767+765+763+761+759
290
- @batch[0].scores["y2"].should == 666+663+660+657+654+651+648+645+642+639
313
+ @batch[0].scores[:tester_y1].should == 777+775+773+771+769+767+765+763+761+759
314
+ @batch[0].scores[:tester_y2].should == 666+663+660+657+654+651+648+645+642+639
291
315
  end
292
316
  end
293
317
 
@@ -0,0 +1,93 @@
1
+ #encoding: utf-8
2
+ require File.join(File.dirname(__FILE__), "./../spec_helper")
3
+
4
+ describe "Machines::MutateCodeblock" do
5
+ before(:each) do
6
+ @twiddler = Machines::MutateCodeblock.new
7
+ @two = Batch.[](
8
+ Answer.new("value «int» \n«int» 1"),
9
+ Answer.new("block { block {value «code»} ref x1 block { block {ref x2}}} \n«code» value «bool» \n«bool» false"))
10
+ end
11
+
12
+
13
+ describe "#build method" do
14
+ it "should respond to :build" do
15
+ @twiddler.should respond_to(:build)
16
+ end
17
+
18
+ it "should respond to :generate as an alias of :build" do
19
+ @twiddler.should respond_to(:generate)
20
+ end
21
+
22
+ it "should raise an error if the argument isn't a Batch" do
23
+ lambda{@twiddler.build(@two)}.should_not raise_error
24
+ lambda{@twiddler.build(99)}.should raise_error
25
+ end
26
+
27
+ it "should produce a Batch" do
28
+ @twiddler.build(@two).should be_a_kind_of(Batch)
29
+ end
30
+
31
+ it "should produce a Batch with a new object_id" do
32
+ @twiddler.build(@two).object_id.should_not == @two.object_id
33
+ end
34
+
35
+ it "should not modify or include any Answer object from its argument Batch" do
36
+ original_ids = @two.collect {|a| a.object_id}
37
+ result_ids = @twiddler.build(@two).collect {|a| a.object_id}
38
+ (original_ids & result_ids).length.should == 0
39
+ end
40
+
41
+ describe ":replicates option" do
42
+ it "should produce a :replicates for each arg Answer, determined by a call option" do
43
+ @twiddler.build(@two, replicates:2).length.should == 2 * @two.length
44
+ end
45
+
46
+ it "should use the initialization :replicates option if there isn't a call option" do
47
+ threefer = Machines::MutateCodeblock.new(replicates:3)
48
+ threefer.build(@two).length.should == 3*@two.length
49
+ end
50
+
51
+ it "should default to replicates:1 if none was set as an option" do
52
+ @twiddler.build(@two).length.should == @two.length
53
+ end
54
+ end
55
+
56
+ it "should increment the :progress attribute of the derived Answers, regardless of other settings" do
57
+ @twiddler.build(@two).each {|a| a.progress.should == 1}
58
+ end
59
+
60
+ describe "mutating code" do
61
+ before(:each) do
62
+ @some_code = ReferencePoint.new(:abcde)
63
+ end
64
+
65
+ it "should replace one program point in each mutant"
66
+
67
+ it "should pick the replaced point with uniform probability" do
68
+ CodeType.should_receive(:any_value).exactly(2).times.and_return(@some_code)
69
+ @twiddler.build(@two)
70
+ end
71
+
72
+ it "should replace a point with one that's the same size if :size_preserving? is true" do
73
+ Kernel.should_not_receive(:rand)
74
+ new_dudes = @twiddler.build(@two, size_preserving?:true)
75
+ new_dudes.each_with_index {|a,idx| a.points.should == @two[idx].points}
76
+ end
77
+
78
+ it "should replace a point with one between 1 and 2xsize if :sizepreserving? is false" do
79
+ Kernel.stub!(:rand).and_return(17)
80
+ CodeType.should_receive(:any_value).at_least(2).times.
81
+ with(hash_including(size_preserving?:false,target_size_in_points:18)).and_return(@some_code)
82
+ @twiddler.build(@two, size_preserving?:false)
83
+ end
84
+
85
+ it "should pass all options through to the any_value call" do
86
+ Kernel.stub!(:rand).and_return(3)
87
+ CodeType.should_receive(:any_value).at_least(2).times.
88
+ with(hash_including(target_size_in_points:4, foo:12)).and_return(@some_code)
89
+ @twiddler.build(@two, foo:12)
90
+ end
91
+ end
92
+ end
93
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: answer-factory
3
3
  version: !ruby/object:Gem::Version
4
- hash: 67
4
+ hash: 65
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
9
  - 3
10
- - 4
11
- version: 0.1.3.4
10
+ - 5
11
+ version: 0.1.3.5
12
12
  platform: ruby
13
13
  authors:
14
14
  - Bill Tozier
@@ -18,7 +18,7 @@ autorequire:
18
18
  bindir: bin
19
19
  cert_chain: []
20
20
 
21
- date: 2010-05-27 00:00:00 -04:00
21
+ date: 2010-06-02 00:00:00 -04:00
22
22
  default_executable: answer-factory
23
23
  dependencies:
24
24
  - !ruby/object:Gem::Dependency
@@ -157,6 +157,7 @@ files:
157
157
  - lib/machines/evaluate_simple_score.rb
158
158
  - lib/machines/evaluate_with_test_cases.rb
159
159
  - lib/machines/infrastructure.rb
160
+ - lib/machines/mutate_codeblock.rb
160
161
  - lib/machines/mutate_footnotes.rb
161
162
  - lib/machines/select_by_summed_rank.rb
162
163
  - lib/machines/select_nondominated.rb
@@ -172,6 +173,7 @@ files:
172
173
  - spec/machines/evaluate_simple_score_spec.rb
173
174
  - spec/machines/evaluate_with_test_cases_spec.rb
174
175
  - spec/machines/infrastructure_spec.rb
176
+ - spec/machines/mutate_codeblock_spec.rb
175
177
  - spec/machines/mutate_footnotes_spec.rb
176
178
  - spec/machines/select_by_summed_rank_spec.rb
177
179
  - spec/machines/select_nondominated_spec.rb
@@ -225,6 +227,7 @@ test_files:
225
227
  - spec/machines/evaluate_simple_score_spec.rb
226
228
  - spec/machines/evaluate_with_test_cases_spec.rb
227
229
  - spec/machines/infrastructure_spec.rb
230
+ - spec/machines/mutate_codeblock_spec.rb
228
231
  - spec/machines/mutate_footnotes_spec.rb
229
232
  - spec/machines/select_by_summed_rank_spec.rb
230
233
  - spec/machines/select_nondominated_spec.rb