boblail/hiccup

View on GitHub
lib/hiccup/inferable/scorer.rb

Summary

Maintainability
A
0 mins
Test Coverage
module Hiccup
  module Inferable
    class Scorer

      def initialize(options={})
        @verbose = options.fetch(:verbose, false)
      end



      def pick_best_guess(guesses, dates)
        scored_guesses = guesses \
          .map { |guess| [guess, score_guess(guess, dates)] } \
          .sort_by { |(guess, score)| -score.to_f }

        if @verbose
          puts "\nGUESSES FOR #{dates}:"
          scored_guesses.each do |(guess, score)|
            puts "  (%.3f p/%.3f b/%.3f c/%.3f) #{guess.humanize}" % [
              score.to_f,
              score.prediction_rate,
              score.brick_penalty,
              score.complexity_penalty]
          end
          puts ""
        end

        scored_guesses.first
      end



      def score_guess(guess, input_dates)
        predicted_dates = guess.occurrences_between(guess.start_date, guess.end_date)

        # prediction_rate is the percent of input dates predicted
        predictions = (predicted_dates & input_dates).length
        prediction_rate = Float(predictions) / Float(input_dates.length)

        # bricks are dates predicted by this guess but not in the input
        bricks = (predicted_dates - input_dates).length

        # brick_rate is the percent of bricks to predictions
        # A brick_rate >= 1 means that this guess bricks more than it predicts
        brick_rate = Float(bricks) / Float(input_dates.length)

        # complexity measures how many rules are necesary
        # to describe the pattern
        complexity = complexity_of(guess)

        # complexity_rate is the number of rules per inputs
        complexity_rate = Float(complexity) / Float(input_dates.length)

        Score.new(prediction_rate, brick_rate, complexity_rate)
      end



      def complexity_of(schedule)
        return schedule.weekly_pattern.length if schedule.weekly?
        return schedule.monthly_pattern.length if schedule.monthly?
        1
      end

    end
  end
end