Last active
December 24, 2022 04:09
-
-
Save suchowan/77a44b8658423054a39e742a45ab4180 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
# -*- coding: utf-8 -*- | |
=begin | |
This script was written by Takashi SUGA on July-August 2017 | |
You may use and/or modify this file according to the license described in the MIT LICENSE.txt file | |
https://raw.githubusercontent.com/suchowan/watson-api-client/master/LICENSE. | |
See also http://suchowan.at.webry.info/201707/article_30.html | |
=end | |
require 'when_exe' | |
require 'combination_generator' | |
# map メソッド | |
class CombinationGenerator | |
def to_a | |
combinations = [] | |
self.each do |combination| | |
combinations << combination | |
end | |
combinations | |
end | |
end | |
# 藤井聡太 対戦相手のレートと勝敗 (2017年9月3日時点) | |
# レートは http://kishi.a.la9.jp/rating.html による | |
# 非公式戦のレートは対局日ではなく公開日のレートを用いた。 | |
Results = %w( | |
1236〇 1436〇 1344〇 1340〇 1661〇 1544〇 1417〇 1555〇 1336〇 1547〇 | |
1594〇 1527〇 1792〇 1503〇 1508〇 1442〇 1591〇 1536〇 1705〇 1773〇 | |
1609〇 1505〇 1612〇 1585〇 1608〇 1571〇 1419〇 1762〇 1712〇 1779● | |
1469〇 1618〇 1702● 1279〇 1489〇 1477〇 1856● 1669〇 1386〇 1645〇 | |
1532〇 1884● 1532● 1687〇) | |
# + %w( | |
# 1675〇 1807● 1554〇 1851● 1752〇 1738〇 1723〇 1785〇 1858〇 1846● | |
# 1618●) | |
# 対戦相手のレート | |
Opponents = Results.map(&:to_i) | |
# 負け数 | |
TotalLoss = Results.select {|result| result =~ /●/ }.length | |
# 負け数マージン | |
LossMargin = 0 | |
# 組み合わせ | |
laptime0 = Time.now.to_f | |
Combinations = (0..(TotalLoss+LossMargin)).to_a.map {|loss| | |
CombinationGenerator.new(loss, (0...Opponents.length).to_a).to_a | |
} | |
p ['laptime', Time.now.to_f - laptime0] | |
# 勝率キャッシュ | |
Rates = {} | |
# レートの種 | |
RateSeed = 1900 | |
# 最尤値キャッシュ | |
estimated = nil | |
# 点推定 | |
def estimate_point | |
estimated ||= When::Ephemeris.root(RateSeed, 0) {|rate| change_rate(rate)} | |
end | |
# 期待負け数 | |
def estimate_loss(rate) | |
(0...Opponents.length).to_a.map {|i| | |
game_probability(Opponents[i]-rate) | |
}.inject(:+) | |
end | |
# レーティング法によるレートの変化 | |
def change_rate(rate) | |
estimate_loss(rate) - TotalLoss | |
end | |
# 区間推定 | |
def estimate_range(threshold=0.05) | |
[[threshold,TotalLoss],[1-threshold,TotalLoss-1]].map {|th,loss| | |
When::Ephemeris.root(RateSeed, th) {|rate| range_probability(rate, loss)} | |
} | |
end | |
# 指定の負け数以下の発生確率 | |
def range_probability(rate, loss_limit) | |
(0..loss_limit).to_a.map {|loss| | |
total_probability(rate, loss) | |
}.sort.inject(:+) | |
end | |
# 指定の負け数の発生確率 | |
def total_probability(rate, loss) | |
Combinations[loss].map {|losses| | |
series_probability(rate, losses) | |
}.sort.inject(:+) | |
end | |
# 指定の勝敗組み合わせの発生確率 | |
def series_probability(rate, losses) | |
(0...Opponents.length).to_a.map {|i| | |
r = rate - Opponents[i] | |
game_probability(losses.include?(i) ? -r : r) | |
}.inject(:*) | |
end | |
# 一局の勝率 | |
def game_probability(r) | |
Rates[r] ||= 1 / (1 + 10.0 ** (-r / 400.0)) | |
end | |
# 点推定(平衡レート) | |
laptime1 = Time.now.to_f | |
p ['---', estimate_point.round(2)] #=> | |
# ["---", 1965.84] | |
laptime2 = Time.now.to_f | |
p ['laptime', laptime2 - laptime1] | |
# 危険率 1%, 2.5%, 5% の場合の区間推定 | |
[0.01, 0.025, 0.05].each do |threshold| | |
p [threshold, estimate_range(threshold).map {|rate| rate.round(2)}] #=> | |
# [0.01, [1770.5, 2219.8]] | |
# [0.025, [1795.46, 2177.1]] | |
# [0.05, [1817.42, 2142.2]] | |
end | |
laptime3 = Time.now.to_f | |
p ['laptime', laptime3 - laptime2] | |
# レートと負け数の関係 | |
losses = {} | |
[1600,1700,1800,1900,2000,2100,2200].each do |rate| | |
losses[rate] = estimate_loss(rate) | |
end | |
(1..(TotalLoss+LossMargin)).each do |loss| | |
losses[When::Ephemeris.root(1800, loss) {|rate| estimate_loss(rate)}] = loss.to_f | |
end | |
losses.keys.sort.each do |rate| | |
p [rate.round(2), losses[rate].round(2)] #=> | |
# [1600.0, 19.98] | |
# [1700.0, 14.78] | |
# [1800.0, 10.28] | |
# [1900.0, 6.77] | |
# [1965.84, 5.0] | |
# [2000.0, 4.24] | |
# [2012.07, 4.0] | |
# [2069.47, 3.0] | |
# [2100.0, 2.56] | |
# [2147.29, 2.0] | |
# [2200.0, 1.51] | |
# [2275.06, 1.0] | |
end | |
laptime4 = Time.now.to_f | |
p ['laptime', laptime4 - laptime3] | |
# 最尤値での負け数ごとの確率 | |
p (0..TotalLoss+LossMargin).to_a.map {|loss| | |
total_probability(estimate_point, loss).round(4) #=> | |
# [0.004, 0.0244, 0.0724, 0.1369, 0.186, 0.1937] | |
} | |
p ['laptime', Time.now.to_f - laptime4] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment