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 = {} | ... | ... |