Create a gist now

Instantly share code, notes, and snippets.

@suchowan /range.rb
Last active Oct 13, 2017

What would you like to do?
# -*- 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年8月4日時点)
# レートは 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●) + %w(
1675〇 1807● 1554〇 1851● 1752〇 1738〇 1723〇 1785〇 1858〇 1846●
)
# 対戦相手のレート
Opponents = Results.map(&:to_i)
# 敗数
TotalLoss = Results.select {|result| result =~ /●/ }.length
# 組み合わせ
Combinations = (0..TotalLoss).to_a.map {|loss|
CombinationGenerator.new(loss, (0...Opponents.length).to_a).to_a
}
# 勝率キャッシュ
Rates = {}
# 点推定
def estimate_point
When::Ephemeris.root(2000, 0) {|rate| change_rate(rate)}
end
# レーティング法によるレートの変化
def change_rate(rate)
(0...Opponents.length).to_a.map {|i|
game_probability(Opponents[i]-rate)
}.inject(:+) - TotalLoss
end
# 区間推定
def estimate_range(threshold=0.05)
[[threshold,TotalLoss],[1-threshold,TotalLoss-1]].map {|th,loss|
When::Ephemeris.root(2000, th) {|rate| total_probability(rate, loss)}
}
end
# 指定の負け数以下の発生確率
def total_probability(rate, loss_limit)
(0..loss_limit).to_a.map {|loss|
Combinations[loss].map {|losses|
series_probability(rate, losses)
}.sort.inject(:+)
}.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
laptime0 = Time.now.to_f
# 点推定(平衡レート)
p ['---', estimate_point] #=>
#      公式戦           公式戦+非公式戦
# ["---", 2022.9828212799807] ["---", 1980.6460262299488]
laptime1 = Time.now.to_f
p laptime1 - laptime0
# 危険率 1%, 5% の場合の区間推定
[0.01, 0.05].each do |threshold|
p [threshold, estimate_range(threshold)] #=>
#      公式戦                     公式戦+非公式戦
# [0.01, [1784.9418908136597, 2372.905372418574]]  [0.01, [1798.732714639248, 2208.5780609548165]]
# [0.05, [1838.7472001974998, 2262.0676622736232]] [0.05, [1843.3603507127536, 2139.6332781023816]]
end
p Time.now.to_f - laptime1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment