Skip to content

Instantly share code, notes, and snippets.

@ikataitsev
Created May 3, 2010 13:29
Show Gist options
  • Save ikataitsev/388087 to your computer and use it in GitHub Desktop.
Save ikataitsev/388087 to your computer and use it in GitHub Desktop.
class Modul # "module" is a keyword in ruby
attr_accessor :name, :size
def initialize(name, size=1)
@name = name
@size = size
end
def inspect
"#{name}(#{size})"
end
def ==(other)
name == other.name && size == other.size
end
# self with size=1
def sample
@sample ||= Modul.new(name)
end
end
class Schedule
attr_accessor :seq, :name, :start_slots
def initialize(seq, name="")
@seq = seq
@name = name
@start_slots = determine_start_slots(@seq)
end
def inspect
seq.inspect
end
def contains?(modul)
seq.include?(modul)
end
# number of modules
def number
seq.size
end
# sum of sizes of all modules
def length
seq.inject(0) {|length, modul| length + modul.size }
end
# constructs a new Schedule object which has 'modul.size' number of sample instances
# of each module instead just each modul instance with an initial size
def sample
sample_seq = []
seq.collect do |modul|
modul.size.times do
sample_seq << modul.sample
end
end
Schedule.new(sample_seq, name)
end
def start_at?(index)
start_slots.include?(index)
end
private
def determine_start_slots(seq)
result = []
seq.each_index do |k|
if k == 0 # first slot is always a start of a module
result << k; next
end
result << result[k-1] + seq[k-1].size
end
result
end
end
#
# "Smart" carousel module scheduler in terms of an access time.
#
class Scheduler
attr_accessor :mode, :noi
def initialize(mode, number_of_iterations=20000)
@mode = mode # :fast or :real
@number_of_iterations = number_of_iterations
end
def average_eta(schedule, modul)
# validation
raise "schedule #{schedule.inspect} doesn't contain the module \'#{modul.inspect}\'" unless schedule.contains?(modul)
sum = 0
if mode == :real
values = Hash.new
@noi.times do
r = rand(schedule.length)
if values.has_key?(r)
sum += values[r]
else
dist = cyclic_distance(schedule, modul, r)
values[r] = dist
sum += dist
end
end
return sum.to_f / @number_of_iterations
end
if mode == :fast # iteration over all possible slots, one time per each
schedule.length.times do |r|
sum += cyclic_distance(schedule, modul, r)
end
return sum.to_f / schedule.length
end
raise "wrong mode \'#{mode}\'"
end
# cyclic distance respecting that a module length can be > 1
# 'rand_index' - a random slot through the schedule
def cyclic_distance(schedule, modul, rand_index)
# validation
raise "schedule #{schedule.inspect} doesn't contain the module \'#{modul.inspect}\'" unless schedule.contains?(modul)
raise "rand_index is out of a schedule's length" if rand_index >= schedule.length
sample_seq = schedule.sample.seq
sample_seq.each_index do |k| # here index 'k' means an index of a slot in a schedule
next unless sample_seq[k] == modul.sample
if k >= rand_index && schedule.start_at?(k)
return k - rand_index
end
end
sample_seq.size - rand_index + sample_seq.index(modul.sample) # cyclic distance in case of rand_index is after the last module
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment