Create a gist now

Instantly share code, notes, and snippets.

@suchowan /range.rb
Last active Jun 17, 2018

Embed
What would you like to do?
# -*- coding: utf-8 -*-
=begin
This script was written by Takashi SUGA on July-June 2018
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/201806/article_18.html
=end
require 'pp'
require 'when_exe'
require 'combination_generator'
# map メソッド
class CombinationGenerator
def to_a
combinations = []
self.each do |combination|
combinations << combination
end
combinations
end
end
# 藤井聡太 対戦相手のレートと勝敗 (2018年06月05日時点)
# レートは http://kishi.a.la9.jp/rating.html による
Results = %w(
1236〇 1436〇 1344〇 1340〇 1661〇 1544〇 1417〇 1557〇 1336〇 1549〇
1594〇 1526〇 1792〇 1503〇 1508〇 1441〇 1591〇 1536〇 1705〇 1772〇
1608〇 1505〇 1611〇 1585〇 1607〇 1572〇 1419〇 1761〇 1712〇 1779●
1469〇 1617〇 1701● 1279〇 1489〇 1477〇 1856● 1666〇 1383〇 1649〇
1540〇 1885● 1540● 1688〇 1651● 1495〇 1376〇 1464〇 1466● 1535〇
1576〇 1650〇 1514〇 1472〇 1634〇 1396〇 1483〇 1670〇 1641● 1563〇
1798● 1689〇 1735〇 1742● 1476〇 1651● 1469〇 1747〇 1819〇 1493〇
1516〇 1543〇 1446〇 1592〇 1509〇 1829〇 1821〇 1616〇 1551〇 1546〇
1737〇 1796〇 1542● 1534〇 1711〇 1628〇 1669〇 1659〇 1478〇 1588〇)
class Rating
# 負け数マージン
LossMargin = 0
# 簡略計算閾値
LossLimit = 5
# レートの種
RateSeed = 2000
# 勝率キャッシュ
Rates = {}
# 組み合わせ
Combinations = []
def initialize(period)
# 期間と、その期間内の結果
@period = period
results =Results[@period]
# 対戦相手のレート
@opponents = results.map(&:to_i)
# 負け数
@total_loss = results.select {|result| result =~ /●/ }.length
return if @total_loss > LossLimit
# 組み合わせ
laptime0 = Time.now.to_f
Combinations[@total_loss] ||= (0..(@total_loss+LossMargin)).to_a.map {|loss|
CombinationGenerator.new(loss, (0...@opponents.length).to_a).to_a
}
p [@period, 'laptime0-1', Time.now.to_f - laptime0]
end
def estimate
# 点推定(平衡レート)
laptime1 = Time.now.to_f
p [@period, @total_loss, 'point_estimation', estimate_point.round(2)]
laptime2 = Time.now.to_f
p [@period, 'laptime1-2', laptime2 - laptime1]
return if @total_loss > LossLimit
# 危険率 2.5% の場合の区間推定
[ 0.025 ].each do |threshold|
p [@period, threshold, estimate_range(threshold).map {|rate| rate.round(2)}] #=>
end
laptime3 = Time.now.to_f
p [@period, 'laptime2-3', laptime3 - laptime2]
=begin
# レートと負け数の関係
losses = {}
[1600,1700,1800,1900,2000,2100,2200].each do |rate|
losses[rate] = estimate_loss(rate)
end
(1..(@total_loss+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 [@period, rate.round(2), losses[rate].round(2)]
end
laptime4 = Time.now.to_f
p [@period, 'laptime3-4', laptime4 - laptime3]
# 最尤値での負け数ごとの確率
p (0..@total_loss+LossMargin).to_a.map {|loss|
total_probability(estimate_point, loss).round(4)
}
p [@period, 'laptime4-5', Time.now.to_f - laptime4]
=end
end
# 点推定
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) - @total_loss
end
# 区間推定
def estimate_range(threshold=0.05)
[[threshold,@total_loss],[1-threshold,@total_loss-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[@total_loss][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
end
(Results.length-29).times do |start|
begin
period = start...(start+30)
rating = Rating.new(period)
rating.estimate
rescue => e
pp e.message
pp e.backtrace
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment