Commit 780cec070170e12adfd6d2ee78b1c1b6fde1498f
1 parent
9a5a6e19
Exists in
master
and in
1 other branch
Improvements to bradley terry calculations
Showing
1 changed file
with
25 additions
and
3 deletions
Show diff stats
app/models/question.rb
| ... | ... | @@ -87,10 +87,17 @@ class Question < ActiveRecord::Base |
| 87 | 87 | sum += item_and_weight[1] |
| 88 | 88 | end |
| 89 | 89 | sum = sum.to_f |
| 90 | - weighted.each { |item, weight| weighted[item] = weight/sum } | |
| 90 | + weighted.each do |item, weight| | |
| 91 | + weighted[item] = weight/sum | |
| 92 | + weighted[item] = 0.0 unless weighted[item].finite? | |
| 93 | + end | |
| 91 | 94 | elsif weighted.instance_of?(Array) |
| 92 | 95 | sum = weighted.inject(0) {|sum, item| sum += item} |
| 93 | - weighted.each_with_index {|item, i| weighted[i] = item/sum} | |
| 96 | + weighted.each_with_index do |item, i| | |
| 97 | + weighted[i] = item/sum | |
| 98 | + weighted[i] = 0.0 unless weighted[i].finite? | |
| 99 | + end | |
| 100 | + | |
| 94 | 101 | end |
| 95 | 102 | end |
| 96 | 103 | |
| ... | ... | @@ -98,6 +105,8 @@ class Question < ActiveRecord::Base |
| 98 | 105 | probs = [] |
| 99 | 106 | prev_probs = [] |
| 100 | 107 | |
| 108 | + fuzz = 0.001 | |
| 109 | + | |
| 101 | 110 | # What ordering key we use is unimportant, just need a consistent way to link index of prob to id |
| 102 | 111 | the_choices = self.choices.sort{|x,y| x.id<=>y.id} |
| 103 | 112 | |
| ... | ... | @@ -112,15 +121,19 @@ class Question < ActiveRecord::Base |
| 112 | 121 | |
| 113 | 122 | t=0 |
| 114 | 123 | probs_size = probs.size |
| 124 | + | |
| 125 | + difference = 1 | |
| 115 | 126 | |
| 116 | 127 | # probably want to add a fuzz here to account for floating rounding |
| 117 | - until probs == prev_probs do | |
| 128 | + while difference > fuzz do | |
| 118 | 129 | s = t % probs_size |
| 119 | 130 | prev_probs = probs.dup |
| 120 | 131 | choice = the_choices[s] |
| 121 | 132 | |
| 122 | 133 | numerator = choice.wins.to_f |
| 123 | 134 | |
| 135 | + | |
| 136 | + | |
| 124 | 137 | denominator = 0.0 |
| 125 | 138 | the_choices.each_with_index do |c, index| |
| 126 | 139 | if(index == s) |
| ... | ... | @@ -128,11 +141,20 @@ class Question < ActiveRecord::Base |
| 128 | 141 | end |
| 129 | 142 | |
| 130 | 143 | wins_and_losses = the_prompts["#{choice.id}, #{c.id}"].votes.size + the_prompts["#{c.id}, #{choice.id}"].votes.size |
| 144 | + | |
| 131 | 145 | denominator+= (wins_and_losses).to_f / (prev_probs[s] + prev_probs[index]) |
| 132 | 146 | end |
| 133 | 147 | probs[s] = numerator / denominator |
| 148 | + # avoid divide by zero NaN | |
| 149 | + probs[s] = 0.0 unless probs[s].finite? | |
| 134 | 150 | normalize!(probs) |
| 135 | 151 | t+=1 |
| 152 | + | |
| 153 | + difference = 0 | |
| 154 | + probs.each_with_index do |curr, index| | |
| 155 | + difference += (curr - prev_probs[index]).abs | |
| 156 | + end | |
| 157 | + puts difference | |
| 136 | 158 | end |
| 137 | 159 | |
| 138 | 160 | probs_hash = {} | ... | ... |