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