Hi @amiika, good idea to code the transitions a->b
into the number as ab
and increase probabilities for a transition through repetition.
But your initialization and normalization does not allow for matrices with 0’s in it. According to my experience, those 0’s are important to exclude transitions. Therefore, I would suggest to initialize the matrix with 0’s:
mm = Array.new(length) { Array.new(length, 0.0) } if mm.is_a?(Integer)
and a modified normalization function. Another aspect is how to deal with matrix dimensions > 9. I think this would require a string as code instead of just a large integer, for example
"1-2-3-10-11-1-2-1"
(or any other character marking the transition).
Here is an example on how it could work (without music, just the helper functions)
# matrix creation and progression
define :to_mm do |idx, mm=8|
# Length of the markov matrix
length = mm.is_a?(Integer) ? mm : mm.length
# Init with random matrix if mm=integer
mm = Array.new(length) { Array.new(length, 0.0) } if mm.is_a?(Integer)
# Treat integer as a markov chain: 121 = 1->2, 2->1
degrees = idx.split("-")
degrees.push(degrees[0]) if degrees.length==1
degrees.each_with_index do |d,i|
if degrees[i+1]
# Overflow depending on mm length: 8->0, 9->1, 0->2
row = (d.to_i==0 ? length : d.to_i-1)%length
column = (degrees[(i+1)].to_i-1)%length
mm[row][column] += 1.0
end
end
# Normalize the resulted matrix
normalize mm
end
define :print_matrix do |mm|
mm.each do |row|
r = ""
row.each do |c|
r += "#{c.round(1)} "
end
puts r
end
end
define :normalize do |mm|
mm.length.times do |row|
pp = 0.0
mm[row].each do |p|
pp += p
end
mm[row].length.times do |i|
if pp == 0.0 then
puts "warning: no transition defined for row #{row+1}!" if i == 0
mm[row][i] = 1.0/mm[row].length
else
mm[row][i] /= pp
end
end
end
mm
end
# function to get next index according to markov matrix mm
define :next_idx do |current_idx, mm|
n = 0
r = rand
pp = 0
mm[current_idx].each do |p|
pp += p
break if pp > r
n += 1
end
return n
end
mm1 = to_mm "1-2-10-2-3-2", 10
print_matrix mm1
EDIT: Just used this new code here: Markov chains for beginners - Part 3