feldtruby 0.3.16 → 0.3.18
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile.lock +9 -2
- data/Rakefile +8 -0
- data/feldtruby.gemspec +6 -0
- data/lib/feldtruby/annotations.rb +10 -0
- data/lib/feldtruby/array/basic_stats.rb +3 -1
- data/lib/feldtruby/array/permutations_and_subsets.rb +17 -0
- data/lib/feldtruby/float.rb +23 -0
- data/lib/feldtruby/logger.rb +216 -30
- data/lib/feldtruby/minitest_extensions.rb +0 -1
- data/lib/feldtruby/mongodb.rb +16 -0
- data/lib/feldtruby/mongodb_logger.rb +245 -0
- data/lib/feldtruby/optimize/differential_evolution.rb +29 -5
- data/lib/feldtruby/optimize/elite_archive.rb +91 -0
- data/lib/feldtruby/optimize/max_steps_termination_criterion.rb +1 -1
- data/lib/feldtruby/optimize/objective.rb +343 -222
- data/lib/feldtruby/optimize/optimizer.rb +138 -60
- data/lib/feldtruby/optimize/search_space.rb +10 -0
- data/lib/feldtruby/optimize.rb +1 -26
- data/lib/feldtruby/statistics.rb +74 -3
- data/lib/feldtruby/time.rb +19 -0
- data/lib/feldtruby/version.rb +1 -1
- data/old/event_logger.rb +682 -0
- data/spikes/comparing_samplers_on_classic_optimization_functions/analyze_sampler_comparison_results.R +78 -0
- data/spikes/comparing_samplers_on_classic_optimization_functions/compare_samplers.rb +264 -0
- data/spikes/comparing_samplers_on_classic_optimization_functions/results_comparing_samplers_130405_175934.csv +561 -0
- data/spikes/comparing_samplers_on_classic_optimization_functions/results_comparing_samplers_levi13_beale_easom_eggholder.csv +11201 -0
- data/spikes/comparing_samplers_on_classic_optimization_functions/results_comparing_samplers_levi13_beale_easom_eggholder_all_radii_4_to_30.csv +44801 -0
- data/spikes/comparing_samplers_on_classic_optimization_functions/results_comparing_samplers_omnitest.csv +1401 -0
- data/spikes/mongodb_logger.rb +47 -0
- data/spikes/simple_de_run.rb +32 -0
- data/test/helper.rb +17 -1
- data/test/test_array_basic_stats.rb +5 -1
- data/test/test_array_permutations_and_subsets.rb +23 -0
- data/test/test_float.rb +15 -0
- data/test/test_html_doc_getter.rb +1 -1
- data/test/test_logger.rb +86 -48
- data/test/test_mongodb_logger.rb +116 -0
- data/test/test_object_annotations.rb +14 -0
- data/test/test_optimize.rb +7 -6
- data/test/test_optimize_differential_evolution.rb +21 -19
- data/test/test_optimize_elite_archive.rb +85 -0
- data/test/test_optimize_objective.rb +237 -74
- data/test/test_optimize_populationbasedoptimizer.rb +72 -6
- data/test/test_optimize_random_search.rb +0 -17
- data/test/test_optimize_search_space.rb +15 -0
- data/test/test_statistics.rb +30 -4
- data/test/test_time.rb +22 -0
- data/test/tmp_shorter.csv +200 -0
- metadata +62 -21
@@ -0,0 +1,78 @@
|
|
1
|
+
#data <- read.csv("/Users/feldt/dev/feldtruby/spikes/results_comparing_samplers_levi13_beale_easom_eggholder.csv")
|
2
|
+
|
3
|
+
source("/Users/feldt/feldt/general/web/advice/statistics/nonparametric_effect_sizes.r")
|
4
|
+
|
5
|
+
data <- read.csv("/Users/feldt/dev/feldtruby/spikes/comparing_samplers_on_classic_optimization_functions/results_comparing_samplers_levi13_beale_easom_eggholder_all_radii_4_to_30.csv")
|
6
|
+
#data <- read.csv("/Users/feldt/dev/feldtruby/spikes/comparing_samplers_on_classic_optimization_functions/results_comparing_samplers_omnitest.csv")
|
7
|
+
data2 <- read.csv("/Users/feldt/dev/feldtruby/spikes/comparing_samplers_on_classic_optimization_functions/results_comparing_samplers_130405_175934.csv")
|
8
|
+
|
9
|
+
# Combine Sampler and Radius into one column and use shorter name for Sampler.
|
10
|
+
data$SamplerRadius <- sapply(data, function(x) paste(ifelse(data$Sampler=="PopulationSampler", "PS", "RL"), data$Radius, sep=""))[,1]
|
11
|
+
data2$SamplerRadius <- sapply(data2, function(x) paste(ifelse(data2$Sampler=="PopulationSampler", "PS", "RL"), data2$Radius, sep=""))[,1]
|
12
|
+
|
13
|
+
# Select only columns we need
|
14
|
+
d <- subset(data, select = c(Problem, SamplerRadius, Q, NumSteps))
|
15
|
+
d2 <- subset(data2, select = c(Problem, SamplerRadius, Q, NumSteps))
|
16
|
+
|
17
|
+
print_mean_per_sampler <- function(d, numsteps) {
|
18
|
+
for(p in levels(unique(d$Problem))) {
|
19
|
+
ds <- subset(d, Problem == p & NumSteps == numsteps)
|
20
|
+
|
21
|
+
cat("Problem = ", p, "\n");
|
22
|
+
print(aggregate(. ~ SamplerRadius, ds, mean));
|
23
|
+
cat("\n");
|
24
|
+
}
|
25
|
+
}
|
26
|
+
|
27
|
+
library(ggplot2)
|
28
|
+
|
29
|
+
pwt <- function(data, problem, numsteps) {
|
30
|
+
d <- subset(data, Problem == problem & NumSteps == numsteps)
|
31
|
+
d$SamplerRadius <- with(d, reorder(SamplerRadius, Q, median))
|
32
|
+
with(d, pairwise.wilcox.test(Q, SamplerRadius))
|
33
|
+
}
|
34
|
+
|
35
|
+
boxplot_numsteps_problem <- function(data, problem, numsteps) {
|
36
|
+
d <- subset(data, Problem == problem & NumSteps == numsteps)
|
37
|
+
d$SamplerRadius <- with(d, reorder(SamplerRadius, Q, median))
|
38
|
+
print(pwt(data, problem, numsteps))
|
39
|
+
p <- ggplot(d, aes(SamplerRadius, Q))
|
40
|
+
p + geom_boxplot()
|
41
|
+
}
|
42
|
+
|
43
|
+
effect.size <- function(data, problem, numsteps, sr1, sr2) {
|
44
|
+
d <- subset(data, Problem == problem & NumSteps == numsteps)
|
45
|
+
d$SamplerRadius <- with(d, reorder(SamplerRadius, Q, median))
|
46
|
+
d1 <- subset(d, SamplerRadius == sr1)
|
47
|
+
d2 <- subset(d, SamplerRadius == sr2)
|
48
|
+
a.statistic(d1$Q, d2$Q)
|
49
|
+
}
|
50
|
+
|
51
|
+
boxplot_numsteps_problem(d, "MinLeviFunctionNum13", 1000)
|
52
|
+
boxplot_numsteps_problem(d, "MinLeviFunctionNum13", 5000)
|
53
|
+
boxplot_numsteps_problem(d, "MinLeviFunctionNum13", 10000)
|
54
|
+
boxplot_numsteps_problem(d, "MinLeviFunctionNum13", 25000)
|
55
|
+
boxplot_numsteps_problem(d, "MinLeviFunctionNum13", 50000)
|
56
|
+
print_mean_per_sampler(d, 10000)
|
57
|
+
|
58
|
+
boxplot_numsteps_problem(d, "MinBealeFunction", 1000)
|
59
|
+
boxplot_numsteps_problem(d, "MinBealeFunction", 5000)
|
60
|
+
boxplot_numsteps_problem(d, "MinBealeFunction", 10000)
|
61
|
+
boxplot_numsteps_problem(d, "MinBealeFunction", 25000)
|
62
|
+
boxplot_numsteps_problem(d, "MinBealeFunction", 50000)
|
63
|
+
effect.size(d, "MinBealeFunction", 50000, "RL4", "RL5")
|
64
|
+
|
65
|
+
boxplot_numsteps_problem(d, "MinEasomFunction", 1000)
|
66
|
+
boxplot_numsteps_problem(d, "MinEasomFunction", 5000)
|
67
|
+
boxplot_numsteps_problem(d, "MinEasomFunction", 10000)
|
68
|
+
boxplot_numsteps_problem(d, "MinEasomFunction", 25000)
|
69
|
+
boxplot_numsteps_problem(d, "MinEasomFunction", 50000)
|
70
|
+
|
71
|
+
boxplot_numsteps_problem(d, "MinEggHolderFunction", 1000)
|
72
|
+
boxplot_numsteps_problem(d, "MinEggHolderFunction", 5000)
|
73
|
+
boxplot_numsteps_problem(d, "MinEggHolderFunction", 10000)
|
74
|
+
boxplot_numsteps_problem(d, "MinEggHolderFunction", 25000)
|
75
|
+
boxplot_numsteps_problem(d, "MinEggHolderFunction", 50000)
|
76
|
+
|
77
|
+
boxplot_numsteps_problem(d, "MinOmniTest", 25000)
|
78
|
+
effect.size(d, "MinOmniTest", 50000, "RL5", "PS15")
|
@@ -0,0 +1,264 @@
|
|
1
|
+
$: << "lib"
|
2
|
+
$: << "../../lib"
|
3
|
+
require 'feldtruby/optimize/differential_evolution'
|
4
|
+
|
5
|
+
# Compare different samplers and their effect on the quality of evolved
|
6
|
+
# solutions.
|
7
|
+
|
8
|
+
$NumSteps = (ARGV[0] && ARGV[0] =~ /^\d+/) ? ARGV[0].to_i : 10_000
|
9
|
+
|
10
|
+
NumSteps1 = [1_000, 5_000, 10_000, 25_000]
|
11
|
+
NumSteps2 = [5_000, 10_000, 25_000, 50_000]
|
12
|
+
|
13
|
+
NumSteps = NumSteps1
|
14
|
+
#NumSteps = NumSteps2
|
15
|
+
|
16
|
+
SamplerRadiuses1 = [
|
17
|
+
["PopulationSampler", 15],
|
18
|
+
["RadiusLimitedPopulationSampler", 5],
|
19
|
+
["RadiusLimitedPopulationSampler", 10],
|
20
|
+
["RadiusLimitedPopulationSampler", 15],
|
21
|
+
["RadiusLimitedPopulationSampler", 20],
|
22
|
+
["RadiusLimitedPopulationSampler", 25],
|
23
|
+
["RadiusLimitedPopulationSampler", 50],
|
24
|
+
]
|
25
|
+
|
26
|
+
SamplerRadiuses2 = (4..30).map do |radius|
|
27
|
+
["RadiusLimitedPopulationSampler", radius]
|
28
|
+
end + [["PopulationSampler", 15]]
|
29
|
+
|
30
|
+
SamplerRadiuses = SamplerRadiuses1
|
31
|
+
#SamplerRadiuses = SamplerRadiuses2
|
32
|
+
|
33
|
+
NumRepetitionsPerSampler = 5
|
34
|
+
|
35
|
+
# This is Lévi function number 13 as stated on the page:
|
36
|
+
# http://en.wikipedia.org/wiki/Test_functions_for_optimization
|
37
|
+
# It has a global minima at f(1,1) = 0. -10 <= x,y <= 10
|
38
|
+
class MinLeviFunctionNum13 < FeldtRuby::Optimize::Objective
|
39
|
+
TwoPi = 2*Math::PI
|
40
|
+
ThreePi = 3*Math::PI
|
41
|
+
|
42
|
+
def objective_min_levi13(candidate)
|
43
|
+
x, y = candidate[0], candidate[1]
|
44
|
+
sin_3pi_x = Math.sin(ThreePi * x)
|
45
|
+
sin_3pi_y = Math.sin(ThreePi * y)
|
46
|
+
sin_2pi_y = Math.sin(TwoPi * y)
|
47
|
+
x_min1 = x - 1.0
|
48
|
+
y_min1 = y - 1.0
|
49
|
+
|
50
|
+
(sin_3pi_x * sin_3pi_x) +
|
51
|
+
(x_min1 * x_min1) * (1 + (sin_3pi_y * sin_3pi_y)) +
|
52
|
+
(y_min1 * y_min1) * (1 + (sin_3pi_y * sin_2pi_y))
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# This is Beale's function as stated on the page:
|
57
|
+
# http://en.wikipedia.org/wiki/Test_functions_for_optimization
|
58
|
+
# It has a global minima at f(3,0.5) = 0. -4.5 <= x,y <= 4.5
|
59
|
+
class MinBealeFunction < FeldtRuby::Optimize::Objective
|
60
|
+
def objective_min_beales_func(candidate)
|
61
|
+
x, y = candidate[0], candidate[1]
|
62
|
+
|
63
|
+
t1 = 1.5 - x + (x*y)
|
64
|
+
t2 = 2.25 - x + (x*y*y)
|
65
|
+
t3 = 2.625 - x + (x*y*y*y)
|
66
|
+
|
67
|
+
(t1*t1) + (t2*t2) + (t3*t3)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# This is Easom's function as stated on the page:
|
72
|
+
# http://en.wikipedia.org/wiki/Test_functions_for_optimization
|
73
|
+
# It has a global minima at f(3,0.5) = 0. -4.5 <= x,y <= 4.5
|
74
|
+
class MinEasomFunction < FeldtRuby::Optimize::Objective
|
75
|
+
def objective_min_easom_func(candidate)
|
76
|
+
x, y = candidate[0], candidate[1]
|
77
|
+
|
78
|
+
f1 = Math.cos(x)
|
79
|
+
|
80
|
+
f2 = Math.cos(y)
|
81
|
+
|
82
|
+
x_min_pi = x - Math::PI
|
83
|
+
y_min_pi = y - Math::PI
|
84
|
+
|
85
|
+
f3 = Math.exp(-(x_min_pi*x_min_pi + y_min_pi*y_min_pi))
|
86
|
+
|
87
|
+
(-f1) * f2 * f3
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# EggHolder function as stated on the page:
|
92
|
+
# http://en.wikipedia.org/wiki/Test_functions_for_optimization
|
93
|
+
class MinEggHolderFunction < FeldtRuby::Optimize::Objective
|
94
|
+
def objective_min_eggholder(candidate)
|
95
|
+
x, y = candidate[0], candidate[1]
|
96
|
+
|
97
|
+
f1 = y + 47.0
|
98
|
+
f2 = Math.sin( Math.sqrt( (y + (x/2.0) + 47.0).abs ) )
|
99
|
+
t1 = (-f1)*f2
|
100
|
+
|
101
|
+
f3 = Math.sin( Math.sqrt( (x - (y + 47.0)).abs ) )
|
102
|
+
t2 = (-x) * f3
|
103
|
+
|
104
|
+
t1 - t2
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
class MinFunctionOfDimension < FeldtRuby::Optimize::Objective
|
109
|
+
attr_accessor :dimension
|
110
|
+
def minimum
|
111
|
+
0.0
|
112
|
+
end
|
113
|
+
def min_solutions
|
114
|
+
@min_solutions ||= ([[0.0] * dimension])
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# Sphere function as stated in the JADE paper:
|
119
|
+
# http://150.214.190.154/EAMHCO/pdf/JADE.pdf
|
120
|
+
class MinSphere < MinFunctionOfDimension
|
121
|
+
def objective_min_func(x)
|
122
|
+
x.inject(0.0) do |sum, xi|
|
123
|
+
sum + (xi*xi)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
# Schwefel 2.22 function as stated in the JADE paper:
|
129
|
+
# http://150.214.190.154/EAMHCO/pdf/JADE.pdf
|
130
|
+
class MinSchwefel2_22 < MinFunctionOfDimension
|
131
|
+
def objective_min_func(x)
|
132
|
+
t1 = x.inject(0.0) do |sum, xi|
|
133
|
+
sum + xi.abs
|
134
|
+
end
|
135
|
+
|
136
|
+
t2 = x.inject(0.0) do |mult, xi|
|
137
|
+
mult * xi.abs
|
138
|
+
end
|
139
|
+
|
140
|
+
t1 + t2
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
# Schwefel 1.2 function as stated in the JADE paper:
|
145
|
+
# http://150.214.190.154/EAMHCO/pdf/JADE.pdf
|
146
|
+
class MinSchwefel1_2 < MinFunctionOfDimension
|
147
|
+
def objective_min_func(x)
|
148
|
+
i = 0
|
149
|
+
sum = 0.0
|
150
|
+
while i < dimension
|
151
|
+
j = 0
|
152
|
+
inner_sum = 0.0
|
153
|
+
while j <= i
|
154
|
+
inner_sum += x[j]
|
155
|
+
j += 1
|
156
|
+
end
|
157
|
+
sum += inner_sum
|
158
|
+
i += 1
|
159
|
+
end
|
160
|
+
|
161
|
+
sum
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
# Schwefel 2.21 function as stated in the JADE paper:
|
166
|
+
# http://150.214.190.154/EAMHCO/pdf/JADE.pdf
|
167
|
+
class MinSchwefel2_21 < MinFunctionOfDimension
|
168
|
+
def objective_min_func(x)
|
169
|
+
max_so_far = x[0].abs
|
170
|
+
(1...dimension).each do |i|
|
171
|
+
max_so_far = x[i] if (x[i] < max_so_far)
|
172
|
+
end
|
173
|
+
max_so_far
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
# This is the OmniTest bi-criteria test function as described in the paper:
|
178
|
+
# Shir et al, "Enhancing Decision Space Diversity in Evolutionary Multiobjective Algorithms", 2009.
|
179
|
+
class MinOmniTest < MinFunctionOfDimension
|
180
|
+
def objective_min_sin(x)
|
181
|
+
x.map {|xi| Math.sin(Math::PI * xi)}.sum
|
182
|
+
end
|
183
|
+
def objective_min_cos(x)
|
184
|
+
x.map {|xi| Math.cos(Math::PI * xi)}.sum
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
Problems1 = [
|
189
|
+
["MinLeviFunctionNum13", ([[-10, 10]] * 2)],
|
190
|
+
["MinBealeFunction", ([[-4.5, 4.5]] * 2)],
|
191
|
+
["MinEasomFunction", ([[-100, 100]] * 2)]
|
192
|
+
]
|
193
|
+
|
194
|
+
Problems2 = [
|
195
|
+
["MinEggHolderFunction", ([[-512, 512]] * 2)]
|
196
|
+
]
|
197
|
+
|
198
|
+
Problems3 = [
|
199
|
+
["MinOmniTest", ([[0, 6]] * 5)]
|
200
|
+
]
|
201
|
+
|
202
|
+
#Problems = Problems1
|
203
|
+
#Problems = Problems2
|
204
|
+
Problems = Problems1 + Problems2
|
205
|
+
#Problems = Problems3
|
206
|
+
|
207
|
+
include FeldtRuby::Optimize
|
208
|
+
|
209
|
+
def best_individual(samplerClass, radius, objectiveKlass, minMaxSpec, numSteps)
|
210
|
+
|
211
|
+
ss = SearchSpace.new_from_min_max_per_variable(minMaxSpec)
|
212
|
+
|
213
|
+
objective = objectiveKlass.new
|
214
|
+
|
215
|
+
de = DEOptimizer.new(objective, ss, {
|
216
|
+
:verbose => true,
|
217
|
+
:maxNumSteps => numSteps,
|
218
|
+
:samplerClass => samplerClass,
|
219
|
+
:samplerRadius => radius})
|
220
|
+
|
221
|
+
start = Time.now
|
222
|
+
best = de.optimize()
|
223
|
+
elapsed_time = Time.now - start
|
224
|
+
|
225
|
+
return best, objective.quality_of(best), elapsed_time
|
226
|
+
|
227
|
+
end
|
228
|
+
|
229
|
+
tstr = Time.now.strftime("%y%m%d_%H%M%S")
|
230
|
+
|
231
|
+
fh = File.open("results_comparing_samplers_#{tstr}.csv", "w")
|
232
|
+
|
233
|
+
# Find the max number of vars for one of the problems
|
234
|
+
MaxNumVars = Problems.map {|p| p[1].length}.max
|
235
|
+
|
236
|
+
ColNamesForVariables = (0...MaxNumVars).map {|i| "X#{i}"}.join(",")
|
237
|
+
|
238
|
+
fh.puts "Problem,Sampler,Radius,Time,NumSteps,Q,#{ColNamesForVariables}"
|
239
|
+
|
240
|
+
Problems.each do |problem, minMaxSpec|
|
241
|
+
|
242
|
+
objectiveKlass = eval problem
|
243
|
+
|
244
|
+
NumSteps.each do |num_steps|
|
245
|
+
|
246
|
+
SamplerRadiuses.each do |sampler, radius|
|
247
|
+
sampler_klass = eval "FeldtRuby::Optimize::#{sampler}"
|
248
|
+
|
249
|
+
NumRepetitionsPerSampler.times do
|
250
|
+
best, qv, elapsed_time = best_individual sampler_klass, radius, objectiveKlass, minMaxSpec, num_steps
|
251
|
+
|
252
|
+
best_str = best.to_a.map {|xi| xi.to_s}.join(",")
|
253
|
+
|
254
|
+
s = "#{problem},#{sampler},#{radius},#{elapsed_time},#{num_steps},#{qv.value},#{best_str}"
|
255
|
+
fh.puts s
|
256
|
+
end
|
257
|
+
|
258
|
+
end
|
259
|
+
|
260
|
+
end
|
261
|
+
|
262
|
+
end
|
263
|
+
|
264
|
+
fh.close
|