Skip to content

Instantly share code, notes, and snippets.

@suchowan
Last active December 24, 2022 04:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save suchowan/77a44b8658423054a39e742a45ab4180 to your computer and use it in GitHub Desktop.
Save suchowan/77a44b8658423054a39e742a45ab4180 to your computer and use it in GitHub Desktop.
# -*- coding: utf-8 -*-
=begin
This script was written by Takashi SUGA on July-September 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月7日時点)
# レートは 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〇 1654●)
# + %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)] #=>
# ["---", 1932.82]
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, [1750.1, 2161.68]]
# [0.025, [1773.96, 2123.75]]
# [0.05, [1794.89, 2092.54]]
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, 20.56]
# [1700.0, 15.21]
# [1800.0, 10.58]
# [1900.0, 6.96]
# [1932.82, 6.0]
# [1971.75, 5.0]
# [2000.0, 4.36]
# [2017.72, 4.0]
# [2074.85, 3.0]
# [2100.0, 2.63]
# [2152.41, 2.0]
# [2200.0, 1.55]
# [2279.92, 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.0012, 0.009, 0.0333, 0.0785, 0.133, 0.1731, 0.1799]
}
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