feldtruby 0.3.16 → 0.3.18

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile.lock +9 -2
  3. data/Rakefile +8 -0
  4. data/feldtruby.gemspec +6 -0
  5. data/lib/feldtruby/annotations.rb +10 -0
  6. data/lib/feldtruby/array/basic_stats.rb +3 -1
  7. data/lib/feldtruby/array/permutations_and_subsets.rb +17 -0
  8. data/lib/feldtruby/float.rb +23 -0
  9. data/lib/feldtruby/logger.rb +216 -30
  10. data/lib/feldtruby/minitest_extensions.rb +0 -1
  11. data/lib/feldtruby/mongodb.rb +16 -0
  12. data/lib/feldtruby/mongodb_logger.rb +245 -0
  13. data/lib/feldtruby/optimize/differential_evolution.rb +29 -5
  14. data/lib/feldtruby/optimize/elite_archive.rb +91 -0
  15. data/lib/feldtruby/optimize/max_steps_termination_criterion.rb +1 -1
  16. data/lib/feldtruby/optimize/objective.rb +343 -222
  17. data/lib/feldtruby/optimize/optimizer.rb +138 -60
  18. data/lib/feldtruby/optimize/search_space.rb +10 -0
  19. data/lib/feldtruby/optimize.rb +1 -26
  20. data/lib/feldtruby/statistics.rb +74 -3
  21. data/lib/feldtruby/time.rb +19 -0
  22. data/lib/feldtruby/version.rb +1 -1
  23. data/old/event_logger.rb +682 -0
  24. data/spikes/comparing_samplers_on_classic_optimization_functions/analyze_sampler_comparison_results.R +78 -0
  25. data/spikes/comparing_samplers_on_classic_optimization_functions/compare_samplers.rb +264 -0
  26. data/spikes/comparing_samplers_on_classic_optimization_functions/results_comparing_samplers_130405_175934.csv +561 -0
  27. data/spikes/comparing_samplers_on_classic_optimization_functions/results_comparing_samplers_levi13_beale_easom_eggholder.csv +11201 -0
  28. data/spikes/comparing_samplers_on_classic_optimization_functions/results_comparing_samplers_levi13_beale_easom_eggholder_all_radii_4_to_30.csv +44801 -0
  29. data/spikes/comparing_samplers_on_classic_optimization_functions/results_comparing_samplers_omnitest.csv +1401 -0
  30. data/spikes/mongodb_logger.rb +47 -0
  31. data/spikes/simple_de_run.rb +32 -0
  32. data/test/helper.rb +17 -1
  33. data/test/test_array_basic_stats.rb +5 -1
  34. data/test/test_array_permutations_and_subsets.rb +23 -0
  35. data/test/test_float.rb +15 -0
  36. data/test/test_html_doc_getter.rb +1 -1
  37. data/test/test_logger.rb +86 -48
  38. data/test/test_mongodb_logger.rb +116 -0
  39. data/test/test_object_annotations.rb +14 -0
  40. data/test/test_optimize.rb +7 -6
  41. data/test/test_optimize_differential_evolution.rb +21 -19
  42. data/test/test_optimize_elite_archive.rb +85 -0
  43. data/test/test_optimize_objective.rb +237 -74
  44. data/test/test_optimize_populationbasedoptimizer.rb +72 -6
  45. data/test/test_optimize_random_search.rb +0 -17
  46. data/test/test_optimize_search_space.rb +15 -0
  47. data/test/test_statistics.rb +30 -4
  48. data/test/test_time.rb +22 -0
  49. data/test/tmp_shorter.csv +200 -0
  50. 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