Optimise calculations based on results

This commit is contained in:
avitex 2017-11-29 12:49:39 +11:00
parent 770a7735df
commit 0ebfbe6447
1 changed files with 17 additions and 27 deletions

View File

@ -59,12 +59,9 @@ defmodule Glicko do
sys_const = Keyword.get(opts, :system_constant, @default_system_constant) sys_const = Keyword.get(opts, :system_constant, @default_system_constant)
conv_tol = Keyword.get(opts, :convergence_tolerance, @default_convergence_tolerance) conv_tol = Keyword.get(opts, :convergence_tolerance, @default_convergence_tolerance)
# Init # Initialization (skips steps 1, 2 and 3)
player_pre_rd_sq = :math.pow(player_pre_rd, 2) player_pre_rd_sq = :math.pow(player_pre_rd, 2)
results = Enum.map(results, &build_internal_result(player_pre_r, &1)) {variance_est, results_effect} = result_calculations(results, player_pre_r)
results_effect = calc_results_effect(results)
# Step 3
variance_est = calc_variance_estimate(results)
# Step 4 # Step 4
delta = calc_delta(results_effect, variance_est) delta = calc_delta(results_effect, variance_est)
# Step 5.1 # Step 5.1
@ -93,24 +90,23 @@ defmodule Glicko do
{player_post_r, player_post_rd, player_post_v} {player_post_r, player_post_rd, player_post_v}
end end
defp build_internal_result(player_pre_r, result) do defp result_calculations(results, player_pre_r) do
result = {variance_estimate_acc, result_effect_acc} =
Map.new Enum.reduce(results, {0.0, 0.0}, fn result, {variance_estimate_acc, result_effect_acc} ->
|> Map.put(:score, Result.score(result)) opponent_rd_g =
|> Map.put(:opponent_r, Result.opponent_rating(result)) result
|> Map.put(:opponent_rd, Result.opponent_rating_deviation(result)) |> Result.opponent_rating_deviation
|> Map.put(:opponent_rd_g, calc_g(Result.opponent_rating_deviation(result))) |> calc_g
Map.put(result, :e, calc_e(player_pre_r, result.opponent_r, result.opponent_rd_g)) win_probability = calc_e(player_pre_r, Result.opponent_rating(result), opponent_rd_g)
end
# Calculation of the estimated variance of the player's rating based on game outcomes {
defp calc_variance_estimate(results) do variance_estimate_acc + :math.pow(opponent_rd_g, 2) * win_probability * (1 - win_probability),
results result_effect_acc + opponent_rd_g * (Result.score(result) - win_probability)
|> Enum.reduce(0.0, fn result, acc -> }
acc + :math.pow(result.opponent_rd_g, 2) * result.e * (1 - result.e) end)
end)
|> :math.pow(-1) {:math.pow(variance_estimate_acc, -1), result_effect_acc}
end end
defp calc_delta(results_effect, variance_est) do defp calc_delta(results_effect, variance_est) do
@ -132,12 +128,6 @@ defmodule Glicko do
:math.exp(a / 2) :math.exp(a / 2)
end end
defp calc_results_effect(results) do
Enum.reduce(results, 0.0, fn result, acc ->
acc + result.opponent_rd_g * (result.score - result.e)
end)
end
defp calc_new_player_rating(results_effect, player_pre_r, player_post_rd) do defp calc_new_player_rating(results_effect, player_pre_r, player_post_rd) do
player_pre_r + :math.pow(player_post_rd, 2) * results_effect player_pre_r + :math.pow(player_post_rd, 2) * results_effect
end end