Created
May 3, 2010 13:29
-
-
Save ikataitsev/388087 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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