Class: FeldtRuby::Optimize::Optimizer

Inherits:
Object
  • Object
show all
Includes:
Logging
Defined in:
lib/feldtruby/optimize/optimizer.rb

Overview

Find an vector of float values that optimizes a given objective.

Direct Known Subclasses

PopulationBasedOptimizer, RandomSearcher

Instance Attribute Summary collapse

Attributes included from Logging

#logger

Instance Method Summary collapse

Methods included from Logging

#__find_logger_set_on_instance_vars, #new_default_logger, #setup_logger_and_distribute_to_instance_variables

Constructor Details

#initialize(objective, searchSpace = FeldtRuby::Optimize::DefaultSearchSpace, options = {}) ⇒ Optimizer

Returns a new instance of Optimizer.


19
20
21
22
23
24
25
26
27
28
29
# File 'lib/feldtruby/optimize/optimizer.rb', line 19

def initialize(objective, searchSpace = FeldtRuby::Optimize::DefaultSearchSpace, options = {})
	@best = nil # To avoid warnings if not set
	@objective, @search_space = objective, searchSpace
	@options = FeldtRuby::Optimize.override_default_options_with(options)

	# Must setup logger before setting options since verbosity of logger is
	# an option!
	setup_logger_and_distribute_to_instance_variables(options)

	initialize_options(@options)
end

Instance Attribute Details

#bestObject (readonly)

Returns the value of attribute best.


16
17
18
# File 'lib/feldtruby/optimize/optimizer.rb', line 16

def best
  @best
end

#best_quality_valueObject (readonly)

Returns the value of attribute best_quality_value.


16
17
18
# File 'lib/feldtruby/optimize/optimizer.rb', line 16

def best_quality_value
  @best_quality_value
end

#best_sub_quality_valuesObject (readonly)

Returns the value of attribute best_sub_quality_values.


17
18
19
# File 'lib/feldtruby/optimize/optimizer.rb', line 17

def best_sub_quality_values
  @best_sub_quality_values
end

#num_optimization_stepsObject (readonly)

Returns the value of attribute num_optimization_steps.


17
18
19
# File 'lib/feldtruby/optimize/optimizer.rb', line 17

def num_optimization_steps
  @num_optimization_steps
end

#objectiveObject (readonly)

Returns the value of attribute objective.


16
17
18
# File 'lib/feldtruby/optimize/optimizer.rb', line 16

def objective
  @objective
end

#optionsObject (readonly)

Returns the value of attribute options.


16
17
18
# File 'lib/feldtruby/optimize/optimizer.rb', line 16

def options
  @options
end

#search_spaceObject (readonly)

Returns the value of attribute search_space.


16
17
18
# File 'lib/feldtruby/optimize/optimizer.rb', line 16

def search_space
  @search_space
end

#termination_criterionObject (readonly)

Returns the value of attribute termination_criterion.


17
18
19
# File 'lib/feldtruby/optimize/optimizer.rb', line 17

def termination_criterion
  @termination_criterion
end

Instance Method Details

#initialize_options(options) ⇒ Object


31
32
33
34
# File 'lib/feldtruby/optimize/optimizer.rb', line 31

def initialize_options(options)
	self.logger.verbose = options[:verbose]
	@termination_criterion = options[:terminationCriterion]
end

#log_end_of_optimizationObject


61
62
63
64
65
66
67
68
69
# File 'lib/feldtruby/optimize/optimizer.rb', line 61

def log_end_of_optimization
	logger.log("End of optimization\n" + 
		"  Optimizer: #{self.class}\n" +
		"  Best found: #{@best}\n" +
		"  Quality of best: #{@objective.quality_of(@best)}\n" +
		"  Time used = #{Time.human_readable_timestr(logger.elapsed_time)}, " + 
		  "Steps performed = #{@num_optimization_steps}, " + 
		  "#{Time.human_readable_timestr(time_per_step, true)}/step")
end

#optimization_stepObject

Run one optimization step. Default is to do nothing, i.e. this is just a superclass, but subclasses need to implement this.


77
78
# File 'lib/feldtruby/optimize/optimizer.rb', line 77

def optimization_step()
end

#optimizeObject

Optimize the objective in the given search space.


37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/feldtruby/optimize/optimizer.rb', line 37

def optimize()
	logger.log "Optimization with optimizer #{self.class.inspect} started"
	@num_optimization_steps = 0
	# Set up a random best since other methods require it
	update_best([search_space.gen_candidate()])
	begin
		while !termination_criterion.terminate?(self)
			new_candidates = optimization_step()
			@num_optimization_steps += 1
			update_best(new_candidates)
		end
	rescue Exception => e
		logger.log_data :exception, {
			:exception_class => e.class.inspect, 
			:backtrace => e.backtrace.join("\n")
		}, "!!! - Optimization FAILED with exception: #{e.message} - !!!" + e.backtrace.join("\n")
	ensure
		logger.log "!!! - Optimization FINISHED after #{@num_optimization_steps} steps - !!!"
	end
	@objective.note_end_of_optimization(self)
	log_end_of_optimization
	@best # return the best
end

#time_per_stepObject


71
72
73
# File 'lib/feldtruby/optimize/optimizer.rb', line 71

def time_per_step
	logger.elapsed_time / @num_optimization_steps
end

#update_best(candidates) ⇒ Object

Update the best if a new best was found.


81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/feldtruby/optimize/optimizer.rb', line 81

def update_best(candidates)
	best_new, rest = objective.rank_candidates(candidates)
	if @best.nil? || @objective.is_better_than?(best_new, @best)
		qb = @best.nil? ? nil : @objective.quality_of(@best)
		logger.log_data :new_best, {
			"New best" => best_new,
			"New quality" => @objective.quality_of(best_new), 
			"Old best" => @best,
			"Old quality" => qb}, "Optimizer (step #{@num_optimization_steps}): New best solution found", true
		@best = best_new
		true
	else
		false
	end
end