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.

[View source]

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

[View source]

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

[View source]

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.

[View source]

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

def optimization_step()
end

#optimizeObject

Optimize the objective in the given search space.

[View source]

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

[View source]

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.

[View source]

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