feldtruby 0.3.18 → 0.4.0
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.
- checksums.yaml +4 -4
- data/Rakefile +11 -1
- data/lib/feldtruby/array/basic_stats.rb +5 -0
- data/lib/feldtruby/logger.rb +22 -10
- data/lib/feldtruby/optimize/differential_evolution.rb +8 -8
- data/lib/feldtruby/optimize/objective.rb +361 -334
- data/lib/feldtruby/optimize/optimizer.rb +7 -8
- data/lib/feldtruby/version.rb +1 -1
- data/spikes/comparing_samplers_on_classic_optimization_functions/compare_samplers.rb +0 -76
- data/test/helper.rb +7 -2
- data/test/long_running/multi_objective_problems.rb +58 -0
- data/test/long_running/single_objective_problems.rb +163 -0
- data/test/long_running/test_single_objective_optimization.rb +112 -0
- data/test/test_array_basic_stats.rb +20 -12
- data/test/test_logger.rb +4 -4
- data/test/test_optimize_objective.rb +175 -119
- metadata +8 -2
@@ -11,13 +11,13 @@ class SingleObjective1 < FeldtRuby::Optimize::Objective
|
|
11
11
|
end
|
12
12
|
|
13
13
|
describe "a single minimizing objective" do
|
14
|
-
|
15
|
-
|
16
|
-
|
14
|
+
before do
|
15
|
+
@o = SingleObjective1.new
|
16
|
+
end
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
18
|
+
it "has one goal" do
|
19
|
+
@o.num_goals.must_equal 1
|
20
|
+
end
|
21
21
|
|
22
22
|
it "can return the name of the goal methods" do
|
23
23
|
@o.goal_methods.sort.must_equal [:goal_min_sum]
|
@@ -43,54 +43,127 @@ describe "a single minimizing objective" do
|
|
43
43
|
@o.is_min_goal_method?("max_anything").must_equal false
|
44
44
|
end
|
45
45
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
it "correctly calculates the quality value and sets up its getter methods" do
|
53
|
-
i1 = [1]
|
54
|
-
q1 = @o.quality_of(i1)
|
55
|
-
q1.value.must_equal 1
|
56
|
-
q1.sub_qualities.must_equal [1]
|
57
|
-
q1.candidate.must_equal i1
|
58
|
-
q1.objective.must_equal @o
|
59
|
-
q1.version.must_equal @o.current_version
|
60
|
-
|
61
|
-
i2 = [1, 2]
|
62
|
-
q2 = @o.quality_of(i2)
|
63
|
-
q2.value.must_equal 3
|
64
|
-
q2.sub_qualities.must_equal [3]
|
65
|
-
q2.candidate.must_equal i2
|
66
|
-
q2.objective.must_equal @o
|
67
|
-
q2.version.must_equal @o.current_version
|
46
|
+
it "correctly calculates the sub-qualitites" do
|
47
|
+
@o.sub_qualities_of([1]).must_equal [1]
|
48
|
+
@o.sub_qualities_of([1, 2]).must_equal [3]
|
49
|
+
@o.sub_qualities_of([1, 2, -45]).must_equal [-42]
|
50
|
+
end
|
68
51
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
52
|
+
describe "a simple case with 3 candidates" do
|
53
|
+
before do
|
54
|
+
@i1 = [1]
|
55
|
+
@q1 = @o.quality_of(@i1)
|
56
|
+
|
57
|
+
@i2 = [1, 2]
|
58
|
+
@q2 = @o.quality_of(@i2)
|
59
|
+
|
60
|
+
@i3 = [1, 2, -45]
|
61
|
+
@q3 = @o.quality_of(@i3)
|
62
|
+
end
|
63
|
+
|
64
|
+
it "correctly calculates the quality value, sets up its getter methods" do
|
65
|
+
i1 = [1]
|
66
|
+
q1 = @o.quality_of(i1)
|
67
|
+
|
68
|
+
q1.value.must_equal 1
|
69
|
+
q1.sub_qualities.must_equal [1]
|
70
|
+
q1.candidate.must_equal i1
|
71
|
+
q1.objective.must_equal @o
|
72
|
+
|
73
|
+
i2 = [1, 2]
|
74
|
+
q2 = @o.quality_of(i2)
|
75
|
+
|
76
|
+
q2.value.must_equal 3
|
77
|
+
q2.sub_qualities.must_equal [3]
|
78
|
+
q2.candidate.must_equal i2
|
79
|
+
q2.objective.must_equal @o
|
80
|
+
|
81
|
+
i3 = [1, 2, -45]
|
82
|
+
q3 = @o.quality_of(i3)
|
83
|
+
|
84
|
+
q3.value.must_equal -42
|
85
|
+
q3.sub_qualities.must_equal [-42]
|
86
|
+
q3.candidate.must_equal i3
|
87
|
+
q3.objective.must_equal @o
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'can hat compare the candidate solutions' do
|
91
|
+
@o.hat_compare(@i3, @i1).must_equal 1
|
92
|
+
@o.hat_compare(@i1, @i3).must_equal -1
|
93
|
+
|
94
|
+
@o.hat_compare(@i1, @i2).must_equal 1
|
95
|
+
@o.hat_compare(@i2, @i1).must_equal -1
|
96
|
+
|
97
|
+
@o.hat_compare(@i3, @i2).must_equal 1
|
98
|
+
@o.hat_compare(@i2, @i3).must_equal -1
|
99
|
+
|
100
|
+
@o.hat_compare(@i1, @i1).must_equal 0
|
101
|
+
@o.hat_compare(@i2, @i2).must_equal 0
|
102
|
+
@o.hat_compare(@i3, @i3).must_equal 0
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'can compare the candidate solutions with is_better_than?' do
|
106
|
+
@o.is_better_than?(@i3, @i1).must_equal true
|
107
|
+
@o.is_better_than?(@i3, @i2).must_equal true
|
108
|
+
@o.is_better_than?(@i1, @i2).must_equal true
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'can compare the quality values with smaller than' do
|
112
|
+
(@q1 < @q3).must_equal true
|
113
|
+
(@q2 < @q3).must_equal true
|
114
|
+
(@q2 < @q1).must_equal true
|
115
|
+
|
116
|
+
(@q3 < @q1).must_equal false
|
117
|
+
(@q3 < @q2).must_equal false
|
118
|
+
(@q1 < @q2).must_equal false
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'can compare the quality values with larger than' do
|
122
|
+
(@q3 > @q1).must_equal true
|
123
|
+
(@q3 > @q2).must_equal true
|
124
|
+
(@q1 > @q2).must_equal true
|
125
|
+
|
126
|
+
(@q1 > @q3).must_equal false
|
127
|
+
(@q2 > @q3).must_equal false
|
128
|
+
(@q2 > @q1).must_equal false
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'can rank different subsets of candidates' do
|
132
|
+
b1, b2, b3 = @o.rank_candidates([@i1, @i2, @i3])
|
133
|
+
b1.must_equal @i3
|
134
|
+
b2.must_equal @i1
|
135
|
+
b3.must_equal @i2
|
136
|
+
|
137
|
+
b1, b2 = @o.rank_candidates([@i1, @i2])
|
138
|
+
b1.must_equal @i1
|
139
|
+
b2.must_equal @i2
|
140
|
+
|
141
|
+
b1, b2 = @o.rank_candidates([@i1, @i3])
|
142
|
+
b1.must_equal @i3
|
143
|
+
b2.must_equal @i1
|
144
|
+
|
145
|
+
b1, b2 = @o.rank_candidates([@i2, @i3])
|
146
|
+
b1.must_equal @i3
|
147
|
+
b2.must_equal @i2
|
148
|
+
end
|
149
|
+
end
|
77
150
|
end
|
78
151
|
|
79
152
|
class TwoMinObjectives1 < FeldtRuby::Optimize::Objective
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
153
|
+
def objective_min_distance_between(candidate)
|
154
|
+
candidate.distance_between_elements.sum
|
155
|
+
end
|
156
|
+
def objective_min_sum(candidate)
|
157
|
+
candidate.sum
|
158
|
+
end
|
86
159
|
|
87
160
|
public :update_global_mins_and_maxs
|
88
161
|
end
|
89
162
|
|
90
163
|
describe "two sub-objectives" do
|
91
|
-
|
92
|
-
|
93
|
-
|
164
|
+
before do
|
165
|
+
@o = TwoMinObjectives1.new
|
166
|
+
end
|
94
167
|
|
95
168
|
it "has two aspects/sub-objectives" do
|
96
169
|
@o.num_goals.must_equal 2
|
@@ -136,14 +209,13 @@ describe "two sub-objectives" do
|
|
136
209
|
@o.sub_qualities_of([1,2,5]).must_equal [4,8]
|
137
210
|
end
|
138
211
|
|
139
|
-
it "correctly calculates the quality value
|
212
|
+
it "correctly calculates the quality value" do
|
140
213
|
i1 = [1,2,3]
|
141
214
|
q1 = @o.quality_of(i1)
|
142
215
|
q1.value.must_equal( 1*((2-1) + (3-2)) + 1*(1+2+3) )
|
143
216
|
q1.sub_qualities.must_equal [2.0, 6.0]
|
144
217
|
q1.candidate.must_equal i1
|
145
218
|
q1.objective.must_equal @o
|
146
|
-
q1.version.must_equal @o.current_version
|
147
219
|
@o.best_candidate.must_equal i1
|
148
220
|
|
149
221
|
i2 = [2,2,2]
|
@@ -152,10 +224,6 @@ describe "two sub-objectives" do
|
|
152
224
|
q2.sub_qualities.must_equal [0.0, 6.0]
|
153
225
|
q2.candidate.must_equal i2
|
154
226
|
q2.objective.must_equal @o
|
155
|
-
q2.version.must_equal @o.current_version
|
156
|
-
# Since 0.0 was smaller than previous minimum for goal 1 the version number
|
157
|
-
# should be updated since the quality eval above.
|
158
|
-
q2.version.must_equal( q1.version + 1 )
|
159
227
|
@o.best_candidate.must_equal i2
|
160
228
|
|
161
229
|
i3 = [2,2,10]
|
@@ -164,11 +232,6 @@ describe "two sub-objectives" do
|
|
164
232
|
q3.sub_qualities.must_equal [8.0, 14.0]
|
165
233
|
q3.candidate.must_equal i3
|
166
234
|
q3.objective.must_equal @o
|
167
|
-
q3.version.must_equal @o.current_version
|
168
|
-
# Since both goals got new max values the version number should have
|
169
|
-
# been bumped by 2.
|
170
|
-
q3.version.must_equal( q2.version + 2 )
|
171
|
-
|
172
235
|
@o.best_candidate.must_equal i2
|
173
236
|
end
|
174
237
|
|
@@ -199,13 +262,10 @@ describe "two sub-objectives" do
|
|
199
262
|
res.length.must_equal 3
|
200
263
|
|
201
264
|
q1 = i1._annotations[@o][:quality]
|
202
|
-
q1.version.must_equal @o.current_version
|
203
265
|
|
204
266
|
q2 = i2._annotations[@o][:quality]
|
205
|
-
q1.version.must_equal @o.current_version
|
206
267
|
|
207
268
|
q3 = i3._annotations[@o][:quality]
|
208
|
-
q3.version.must_equal @o.current_version
|
209
269
|
end
|
210
270
|
|
211
271
|
it "updates the quality value if old when calling quality_of" do
|
@@ -214,7 +274,6 @@ describe "two sub-objectives" do
|
|
214
274
|
i2 = [1,1,1]
|
215
275
|
q2 = @o.quality_of(i2)
|
216
276
|
q1b = @o.quality_of(i1)
|
217
|
-
q1b.version.must_equal q2.version
|
218
277
|
end
|
219
278
|
|
220
279
|
it "updates the quality value if old when calling rank_candidates" do
|
@@ -225,75 +284,73 @@ describe "two sub-objectives" do
|
|
225
284
|
res = @o.rank_candidates([i1, i2])
|
226
285
|
|
227
286
|
q1 = i1._annotations[@o][:quality]
|
228
|
-
q1.version.must_equal @o.current_version
|
229
287
|
|
230
288
|
q2 = i2._annotations[@o][:quality]
|
231
|
-
q1.version.must_equal @o.current_version
|
232
289
|
end
|
233
290
|
end
|
234
291
|
|
235
292
|
describe "the objective itself and its updates" do
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
293
|
+
before do
|
294
|
+
@o = SingleObjective1.new
|
295
|
+
@o2 = TwoMinObjectives1.new
|
296
|
+
@c = [1,2,3]
|
297
|
+
end
|
298
|
+
|
299
|
+
it "repeatedly returns the same quality value for an object unless the objective itself has been changed" do
|
300
|
+
qv = @o.quality_of(@c)
|
301
|
+
qv.must_equal @o.quality_of(@c)
|
302
|
+
end
|
303
|
+
|
304
|
+
it "returns different quality values for different objectives" do
|
305
|
+
qv = @o.quality_of(@c)
|
306
|
+
qv2 = @o2.quality_of(@c)
|
307
|
+
qv.wont_equal qv2
|
308
|
+
end
|
309
|
+
|
310
|
+
it "we get the same quality object even if the objective has changed" do
|
311
|
+
qv = @o2.quality_of(@c)
|
312
|
+
@o2.quality_of([1,2,3,4,5]) # Higher sum so max updated
|
313
|
+
qvnew = @o2.quality_of(@c)
|
314
|
+
qvnew.must_be_same_as qv
|
315
|
+
end
|
259
316
|
|
260
317
|
it "can compare two candidates directly" do
|
261
318
|
@o.is_better_than?([1], [2]).must_equal true
|
262
319
|
@o.is_better_than?([3], [2]).must_equal false
|
263
320
|
|
264
|
-
|
265
|
-
|
266
|
-
@o.is_better_than?([3,
|
267
|
-
end
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
321
|
+
@o.is_better_than?([3, 2], [2, 2]).must_equal false
|
322
|
+
@o.is_better_than?([3, 1], [2, 2]).must_equal false
|
323
|
+
@o.is_better_than?([3, 0.5], [2, 2]).must_equal true
|
324
|
+
end
|
325
|
+
|
326
|
+
describe "version numbers" do
|
327
|
+
it "has version number 0 when no evaluation has taken place" do
|
328
|
+
@o.current_version.must_equal 0
|
329
|
+
@o2.current_version.must_equal 0
|
330
|
+
end
|
331
|
+
|
332
|
+
it "increases the version number also for single goal objectives" do
|
333
|
+
@o.quality_of([1])
|
334
|
+
@o.current_version.must_equal 2 # min and max changed
|
335
|
+
end
|
336
|
+
|
337
|
+
it "increases the version number each time a quality aspect of a candidate is more extreme than previously seen (when multi-objective)" do
|
338
|
+
@o2.quality_of([1])
|
339
|
+
@o2.current_version.must_equal 4 # Both min and max changed for two objectives => 2*2
|
340
|
+
@o2.quality_of([2])
|
341
|
+
@o2.current_version.must_equal 5 # New max values for sum objective => +1
|
342
|
+
@o2.quality_of([1,2])
|
343
|
+
@o2.current_version.must_equal 7 # New max values for both objectives => +2
|
344
|
+
@o2.quality_of([0])
|
345
|
+
@o2.current_version.must_equal 8 # New min value for sum objective => +1
|
346
|
+
@o2.quality_of([-1])
|
347
|
+
@o2.current_version.must_equal 9 # New min value for sum objective => +1
|
348
|
+
@o2.quality_of([-2])
|
349
|
+
@o2.current_version.must_equal 10 # New min value for sum objective => +1
|
350
|
+
@o2.quality_of([1,2,3])
|
351
|
+
@o2.current_version.must_equal 12 # New max for both objectives => +1
|
352
|
+
end
|
353
|
+
end
|
297
354
|
end
|
298
355
|
|
299
356
|
class OneMinOneMaxObjective1 < FeldtRuby::Optimize::Objective
|
@@ -350,7 +407,6 @@ describe "calculating quality with weights" do
|
|
350
407
|
q1.sub_qualities.must_equal [2.0, 6.0]
|
351
408
|
q1.candidate.must_equal i1
|
352
409
|
q1.objective.must_equal @o
|
353
|
-
q1.version.must_equal @o.current_version
|
354
410
|
|
355
411
|
@o.weights = {:objective_min_distance_between => 5, :objective_max_sum => 30}
|
356
412
|
q2 = @o.quality_of(i1)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: feldtruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Feldt
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-04-
|
11
|
+
date: 2013-04-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rinruby
|
@@ -147,6 +147,9 @@ files:
|
|
147
147
|
- spikes/simple_de_run.rb
|
148
148
|
- spikes/zlib_for_short_strings.rb
|
149
149
|
- test/helper.rb
|
150
|
+
- test/long_running/multi_objective_problems.rb
|
151
|
+
- test/long_running/single_objective_problems.rb
|
152
|
+
- test/long_running/test_single_objective_optimization.rb
|
150
153
|
- test/skip_test_array_archive.rb
|
151
154
|
- test/test_array.rb
|
152
155
|
- test/test_array_basic_stats.rb
|
@@ -202,6 +205,9 @@ specification_version: 4
|
|
202
205
|
summary: Robert Feldt's Common Ruby Code lib
|
203
206
|
test_files:
|
204
207
|
- test/helper.rb
|
208
|
+
- test/long_running/multi_objective_problems.rb
|
209
|
+
- test/long_running/single_objective_problems.rb
|
210
|
+
- test/long_running/test_single_objective_optimization.rb
|
205
211
|
- test/skip_test_array_archive.rb
|
206
212
|
- test/test_array.rb
|
207
213
|
- test/test_array_basic_stats.rb
|