class Statfeed

Constants

VERSION

Attributes

accents[RW]
choices[RW]
decisions[RW]
heterogeneities[RW]
options[RW]
randoms[RW]
size[RW]
statistics[RW]
weights[RW]

Public Class Methods

new(decisions, options, heterogeneity: 0.1, accent: 1.0) click to toggle source
# File lib/statfeed.rb, line 5
def initialize decisions, options, heterogeneity: 0.1, accent: 1.0
  @decisions = decisions
  @options = options

  # This will eventually be the result of applying statistical feedback
  @choices = Array.new(@decisions.size, nil)

  # Vector of heterogeneity values for each decision
  @heterogeneities = Array.new(decisions.size, heterogeneity)
  # Vector of accent values for each decision
  @accents = Array.new(decisions.size, accent)
  # Vector of statistic for each option
  reset_statistics

  # Fill matrix of random values
  populate_randoms
  # Fill matrix of weights
  populate_weights
end

Public Instance Methods

acceptable?(*args) click to toggle source

Default is “everything's okay”

# File lib/statfeed.rb, line 42
def acceptable? *args
  true
end
expected_increment(decision, option) click to toggle source
# File lib/statfeed.rb, line 62
def expected_increment decision, option
  (@accents[decision] + (@heterogeneities[decision] * @randoms[decision][option])).to_f / @weights[decision][option]
end
increment_statistics(decision, option) click to toggle source
# File lib/statfeed.rb, line 90
def increment_statistics decision, option
  @statistics[option] += true_increment(decision, option)
end
normalization_value(decision) click to toggle source
# File lib/statfeed.rb, line 70
def normalization_value decision
  @accents[decision].to_f / @weights[decision].inject(0.0, :+)
end
normalize_statistics(decision) click to toggle source
# File lib/statfeed.rb, line 94
def normalize_statistics decision
  @statistics.each_with_index.map do |statistic, m|
    if @weights[decision][m] > 0.0
      statistic - normalization_value(decision)
    else
      statistic
    end
  end
end
normalize_statistics!(decision) click to toggle source
# File lib/statfeed.rb, line 104
def normalize_statistics! decision
  @statistics = normalize_statistics decision
end
populate_choices() click to toggle source
# File lib/statfeed.rb, line 29
def populate_choices
  @choices.tap do |choices|
    @decisions.each_index do |decision|
      options = sort_options(scheduling_values(decision))
      index = options.find_index {|o| acceptable? o, decision}
      choices[decision] = options[index]
      increment_statistics decision, index
      normalize_statistics! decision
    end
  end
end
populate_randoms() click to toggle source
# File lib/statfeed.rb, line 46
def populate_randoms
  @randoms = Array.new @decisions.size do
    Array.new @options.size do
      rand
    end
  end
end
populate_weights() click to toggle source
# File lib/statfeed.rb, line 54
def populate_weights
  @weights = Array.new @decisions.size do
    Array.new @options.size do
      1.0 / @options.size
    end
  end
end
reset_statistics() click to toggle source
# File lib/statfeed.rb, line 25
def reset_statistics
  @statistics = Array.new(options.size, 0.0)
end
sample() { |index| ... } click to toggle source
# File lib/statfeed.rb, line 108
def sample
  # Accumulator value
  acc = 0.0
  # Map the cumulative weights
  cdf = @weights.map { |w| acc += w }
  # Get a random number between 0.0 and the last value
  r = rand(cdf.last)
  # Gets the first number that's less than the random number
  index = cdf.find_index { |c| c > r }
  
  @weights = @weights.map { |w|
    # Increment the full thing by a total of 1.0
    w += (@weights[index].to_f / (@weights.size-1.0))
  }
  @weights[index] = 0

  if block_given?
    yield index
  else
    index
  end
end
scheduling_values(decision) click to toggle source
# File lib/statfeed.rb, line 74
def scheduling_values decision
  (0...@options.size).map do |m|
    @statistics[m] + expected_increment(decision, m)
  end
end
sort_option_indices(vals) click to toggle source

Feed the scheduling values into this (step 2)

# File lib/statfeed.rb, line 86
def sort_option_indices vals
  (0...@options.size).to_a.zip(vals).sort_by(&:last).map(&:first)
end
sort_options(vals) click to toggle source

Feed the scheduling values into this (step 2)

# File lib/statfeed.rb, line 81
def sort_options vals
  @options.zip(vals).sort_by(&:last).map(&:first)
end
true_increment(decision, option) click to toggle source
# File lib/statfeed.rb, line 66
def true_increment decision, option
  @accents[decision].to_f / @weights[decision][option]
end