Class: FeldtRuby::Optimize::StdOutLogger

Inherits:
Object
  • Object
show all
Defined in:
lib/feldtruby/optimize/stdout_logger.rb

Defined Under Namespace

Classes: DummyStream

Instance Method Summary collapse

Constructor Details

#initialize(optimizer, verbose = true) ⇒ StdOutLogger

Returns a new instance of StdOutLogger.



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/feldtruby/optimize/stdout_logger.rb', line 11

def initialize(optimizer, verbose = true)
	@optimizer = optimizer
	@verbose = verbose
	@start_time = Time.now # To ensure we have a value even if optimizer forgot calling note_optimization_starts
	@events = Hash.new(0)
	# Old version of Time does not take a data as argument so use utc for those cases
	if RUBY_VERSION < "1.9"
		@last_report_time = Hash.new(Time.utc(1970, "jan", 1))
	else			
		@last_report_time = Hash.new(Time.new("1970-01-01")) # Maps event strings to the last time they were reported on, used by anote.
	end
	if verbose
		@outstream = STDOUT
	else
		@outstream = DummyStream.new
	end
end

Instance Method Details

#adaptive_note(frequency, msg, values = []) ⇒ Object

Adaptive notes are recorded as any (normal) notes but is only reported to the user in a readable manner i.e. the frequency of reporting them is limited.



55
56
57
58
59
# File 'lib/feldtruby/optimize/stdout_logger.rb', line 55

def adaptive_note(frequency, msg, values = [])
	should_print = elapsed_since_last_reporting_of(msg) > frequency
	@last_report_time[msg] = Time.now if should_print
	internal_note should_print, msg, values
end

#anote(msg, *values) ⇒ Object



61
62
63
# File 'lib/feldtruby/optimize/stdout_logger.rb', line 61

def anote(msg, *values)
	adaptive_note(2.0, msg, values)
end

#elapsed_since_last_reporting_of(msg) ⇒ Object



65
66
67
# File 'lib/feldtruby/optimize/stdout_logger.rb', line 65

def elapsed_since_last_reporting_of(msg)
	Time.now - @last_report_time[msg]
end

#elapsed_timeObject



140
141
142
# File 'lib/feldtruby/optimize/stdout_logger.rb', line 140

def elapsed_time
	Time.now - @start_time
end

#event_stat_in_relation_to_step(eventCount) ⇒ Object



84
85
86
# File 'lib/feldtruby/optimize/stdout_logger.rb', line 84

def event_stat_in_relation_to_step(eventCount)
	"#{eventCount} times (%.3f times/step)" % (eventCount.to_f / num_steps)
end

#event_summary_to_strObject



80
81
82
# File 'lib/feldtruby/optimize/stdout_logger.rb', line 80

def event_summary_to_str()
	"Event counts:\n    " + @events.to_a.map {|key,count| "#{key}: #{event_stat_in_relation_to_step(count)}"}.join("\n    ")
end

#info_about_candidate(candidate, qualityValue, subQualityValues, nameString = "new") ⇒ Object



88
89
90
91
# File 'lib/feldtruby/optimize/stdout_logger.rb', line 88

def info_about_candidate(candidate, qualityValue, subQualityValues, nameString = "new")
	info_str = nameString ? "#{nameString} = #{candidate.inspect}\n  " : "  "
	info_str + candidate._quality_value.inspect
end

#internal_note(shouldPrint, msg, values) ⇒ Object



34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/feldtruby/optimize/stdout_logger.rb', line 34

def internal_note(shouldPrint, msg, values)
	@events[msg] += 1
	if (values.all? {|e| String === e})
		vstr = values.join("\n  ")
	else
		vstr = values.inspect
	end
	if msg == "."
		# Just a tick so no event stat etc
		log_print( msg ) if shouldPrint
	else
		log( "#{event_stat_in_relation_to_step(@events[msg])}: #{msg}\n  #{vstr}", true ) if shouldPrint
	end
end

#log(str, newlineBefore = false, newlineAfter = true) ⇒ Object



120
121
122
123
124
125
# File 'lib/feldtruby/optimize/stdout_logger.rb', line 120

def log(str, newlineBefore = false, newlineAfter = true)
	@outstream.puts "" if newlineBefore
	@outstream.print "#{Time.timestamp({:short => true})} #{num_steps}: (#{Time.human_readable_timestr(elapsed_time)}), #{str}"
	@outstream.puts "" if newlineAfter
	@outstream.flush
end

#log_print(str) ⇒ Object



127
128
129
130
# File 'lib/feldtruby/optimize/stdout_logger.rb', line 127

def log_print(str)
	@outstream.print str
	@outstream.flush
end

#note(msg, *values) ⇒ Object



49
50
51
# File 'lib/feldtruby/optimize/stdout_logger.rb', line 49

def note(msg, *values)
	internal_note true, msg, values
end

#note_another_optimization_step(stepNumber) ⇒ Object



107
108
109
110
# File 'lib/feldtruby/optimize/stdout_logger.rb', line 107

def note_another_optimization_step(stepNumber)
	@events['Optimization steps'] += 1 # we note it by hand since we are printing something different than the event name
	adaptive_note(0.1, '.')
end

#note_end_of_optimization(optimizer) ⇒ Object



69
70
71
72
73
74
75
76
77
78
# File 'lib/feldtruby/optimize/stdout_logger.rb', line 69

def note_end_of_optimization(optimizer)
	best_msg = info_about_candidate(optimizer.best, optimizer.best_quality_value, 
		optimizer.best_sub_quality_values, "best")
	note("End of optimization", "Optimizer: #{optimizer.class}", 
		best_msg, 
		event_summary_to_str(),
		"Time used = #{Time.human_readable_timestr(elapsed_time)}, " + 
		"Steps performed = #{num_steps}, " + 
		"#{Time.human_readable_timestr(time_per_step, true)}/step")
end

#note_new_best(newBest, newQv, newSubQvs, oldBest = nil, oldQv = nil, oldSubQvs = nil) ⇒ Object



98
99
100
101
102
103
104
105
# File 'lib/feldtruby/optimize/stdout_logger.rb', line 98

def note_new_best(newBest, newQv, newSubQvs, oldBest = nil, oldQv = nil, oldSubQvs = nil)
	new_best_msg = info_about_candidate(newBest, newQv, newSubQvs, "new")
	if oldBest
		new_best_msg += ",\n  supplants old best\n  #{oldQv.inspect}"
		new_best_msg += "\n  #{newQv.improvement_in_relation_to(oldQv)}\n"
	end
	anote("Found new best", new_best_msg)
end

#note_new_better(betterMsg, newBetter, newQv, newSubQvs) ⇒ Object



93
94
95
96
# File 'lib/feldtruby/optimize/stdout_logger.rb', line 93

def note_new_better(betterMsg, newBetter, newQv, newSubQvs)
	new_better_msg = info_about_candidate(newBetter, newQv, newSubQvs, nil)
	anote(betterMsg, new_better_msg)
end

#note_optimization_startsObject



29
30
31
32
# File 'lib/feldtruby/optimize/stdout_logger.rb', line 29

def note_optimization_starts
	log("Optimization with optimizer #{@optimizer.class.inspect} started")
	@start_time = Time.now
end

#note_termination(message) ⇒ Object



116
117
118
# File 'lib/feldtruby/optimize/stdout_logger.rb', line 116

def note_termination(message)
	log(message, true)
end

#num_stepsObject



132
133
134
# File 'lib/feldtruby/optimize/stdout_logger.rb', line 132

def num_steps
	@events['Optimization steps']
end

#quality_values_to_str(qv, subQvs) ⇒ Object



112
113
114
# File 'lib/feldtruby/optimize/stdout_logger.rb', line 112

def quality_values_to_str(qv, subQvs)
	"q = %.4f, subqs = %s" % [qv, subQvs.map {|v| v.round_to_decimals(4)}.inspect]
end

#time_per_stepObject



136
137
138
# File 'lib/feldtruby/optimize/stdout_logger.rb', line 136

def time_per_step
	elapsed_time / num_steps
end