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
@@ -1,11 +1,12 @@
1
1
  require 'feldtruby/optimize/optimizer'
2
2
  require 'feldtruby/math/rand'
3
3
  require 'feldtruby/vector'
4
+ require 'feldtruby/logger'
4
5
 
5
6
  module FeldtRuby::Optimize
6
7
 
7
8
  # Common to many Evolutionary Computation optimizers
8
- class EvolutionaryOptimizer < PopulationBasedOptimizer; end
9
+ class EvolutionaryOptimizer < FeldtRuby::Optimize::PopulationBasedOptimizer; end
9
10
 
10
11
  # Base class for Differential Evolution (DE) for continuous, real-valued optimization.
11
12
  # Since there are many different DE variants this is the base class
@@ -57,12 +58,13 @@ class DEOptimizerBase < EvolutionaryOptimizer
57
58
  def optimization_step()
58
59
  trial, target, target_index = generate_trial_candidate_and_target()
59
60
 
60
- # We get [candidate, qualityValue, subQualityValues] for each vector
61
61
  best, worst = objective.rank_candidates([target, trial])
62
62
 
63
63
  # Supplant the target vector with the trial vector if better
64
- if best.first != target
65
- @logger.note_new_better("Trial vector was better", *best)
64
+ if best != target
65
+ logger.log_data :better_candidate_found, {
66
+ :better => best,
67
+ :quality => @objective.quality_of(best)}, "Trial vector was better"
66
68
  trial_better = true
67
69
  update_candidate_in_population(target_index, trial)
68
70
  else
@@ -72,7 +74,7 @@ class DEOptimizerBase < EvolutionaryOptimizer
72
74
  # Give feedback to strategy since some strategies use this to self-adapt
73
75
  feedback_on_trial_vs_target(trial, target, trial_better)
74
76
 
75
- [best.first]
77
+ [best]
76
78
  end
77
79
 
78
80
  #####################################
@@ -183,4 +185,26 @@ class DEOptimizer < DEOptimizerBase
183
185
  include DE_MutationStrategy_Rand_1
184
186
  end
185
187
 
188
+ # Optimize the _numVariables_ between the _min_ and _max_ values given _costFunction_.
189
+ # Default is to minimize.
190
+ def self.optimize(min, max, options = {:verbose => true},
191
+ objectiveFuncClass = FeldtRuby::Optimize::ObjectiveMinimizeBlock, &costFunction)
192
+ objective = objectiveFuncClass.new(&costFunction)
193
+ num_vars = costFunction.arity
194
+ search_space = SearchSpace.new_from_min_max(num_vars, min, max)
195
+ optimizer = DEOptimizer.new(objective, search_space, options)
196
+ optimizer.optimize()
197
+ optimizer.best.to_a
198
+ end
199
+
200
+ # Short hand wrapper for function minimization.
201
+ def self.minimize(min, max, options = {}, &costFunction)
202
+ optimize(min, max, options, &costFunction)
203
+ end
204
+
205
+ # Short hand wrapper for function maximization.
206
+ def self.maximize(min, max, options = {}, &costFunction)
207
+ optimize(min, max, options, FeldtRuby::Optimize::ObjectiveMaximizeBlock, &costFunction)
208
+ end
209
+
186
210
  end
@@ -0,0 +1,91 @@
1
+ require 'feldtruby/optimize'
2
+
3
+ module FeldtRuby::Optimize
4
+
5
+ # This keeps a record of the best/elite candidate solutions found during
6
+ # an optimization search. It keeps separate top lists per goal being optimized
7
+ # as well as for the aggregate quality value (fitness) itself. The top lists
8
+ # are all sorted to allow for fast checks and insertion.
9
+ class EliteArchive
10
+ DefaultParams = {
11
+ :NumTopPerGoal => 10,
12
+ :NumTopAggregate => 25
13
+ }
14
+
15
+ attr_reader :objective, :top_per_goal, :best
16
+
17
+ def initialize(objective, options = DefaultParams.clone)
18
+ @objective = objective
19
+ @options = options
20
+ init_top_lists
21
+ end
22
+
23
+ # A top list is an array of a fixed size that saves the top candidates
24
+ # based on their quality values.
25
+ class GlobalTopList
26
+ def initialize(maxSize, objective)
27
+ @max_size =maxSize
28
+ @top_list = Array.new
29
+ @objective = objective
30
+ end
31
+ def length; @top_list.length; end
32
+
33
+ def [](index)
34
+ @top_list[index]
35
+ end
36
+
37
+ def add(candidate)
38
+ last = @top_list.last
39
+ #puts "In #{self},\nlast = #{last}, candidate = #{candidate}, top_list = #{@top_list}"
40
+ if @top_list.length < @max_size || last.nil? || is_better_than?(candidate, last)
41
+ @top_list.pop if @top_list.length >= @max_size
42
+ @top_list << candidate
43
+ @top_list = sort_top_list
44
+ end
45
+ #puts "top_list = #{@top_list}"
46
+ end
47
+
48
+ def is_better_than?(candidate1, candidate2)
49
+ @objective.is_better_than?(candidate1, candidate2)
50
+ end
51
+
52
+ def sort_top_list
53
+ @top_list.sort_by {|c| @objective.quality_of(c).value}
54
+ end
55
+
56
+ def inspect
57
+ self.class.inspect + @top_list.inspect
58
+ end
59
+ end
60
+
61
+ class GoalTopList < GlobalTopList
62
+ def initialize(maxSize, objective, goalIndex)
63
+ super(maxSize, objective)
64
+ @index = goalIndex
65
+ end
66
+ def is_better_than?(candidate1, candidate2)
67
+ @objective.is_better_than_for_goal?(@index, candidate1, candidate2)
68
+ end
69
+ def sort_top_list
70
+ @top_list.sort_by {|c|
71
+ qv = @objective.quality_of(c)
72
+ qv.sub_quality(@index, true) # We want the sub quality value posed as a minimization goal regardless of whether it is a min or max goal
73
+ }
74
+ end
75
+ end
76
+
77
+ def init_top_lists
78
+ @top_per_goal = Array.new
79
+ @objective.num_goals.times do |i|
80
+ @top_per_goal << GoalTopList.new(@options[:NumTopPerGoal], @objective, i)
81
+ end
82
+ @best = GlobalTopList.new(@options[:NumTopAggregate], @objective)
83
+ end
84
+
85
+ def add(candidate)
86
+ @best.add candidate
87
+ @top_per_goal.each {|tl| tl.add(candidate)}
88
+ end
89
+ end
90
+
91
+ end
@@ -15,7 +15,7 @@ end
15
15
  class FeldtRuby::Optimize::MaxStepsTerminationCriterion < FeldtRuby::Optimize::TerminationCriterion
16
16
  attr_accessor :max_steps
17
17
 
18
- def initialize(maxSteps = 1000)
18
+ def initialize(maxSteps = 10_000)
19
19
  @max_steps = maxSteps
20
20
  end
21
21
  def terminate?(optimizer)