LoginSignup
1
0

More than 3 years have passed since last update.

昇級・降級枠の変化による順位戦シミュレーション

Last updated at Posted at 2019-06-10

はじめに

以前はスイス式に関する考察を行ったが、

ランダムマッチングとスイス式による順位戦のシミュレーション

今回は昇級・降級枠が変化した時に利害がどう変わるのかを調べる。

昇級

  • 2人と3人のときでどう変わるかを見る。
  • リーグは50人。
  • 順位1位からレーティング差が10ずつ離れているとする。(1位と50位ではR500ほど違うことになる)

この仮定だと前回のプログラムがほぼそのまま使える。

# 順位戦シミュレーション
def normal_simulation(rank_up_number: int):
    rank_up = []
    runner_up = []
    for x in range(simulation_number):
        league = League(player_number)
        for i in range(battle_number):
            league.random_match(i)
            league.battles(i)
        league.count_win()
        league.result_rank()
        rank_up.extend(league.result_rank_list[0:rank_up_number])
        runner_up.append(league.players[league.result_rank_list[rank_up_number]].win)
        if x % 1000 == 0:
                print(x)
    return rank_up, runner_up

def analyze_result(rank_up, runner_up):
    rank_up_list = [0] * player_number
    runner_up_list = [0] * 11
    for i in range(player_number):
        rank_up_list[i] = rank_up.count(i)
    for i in range(11):
        runner_up_list[i] = runner_up.count(i)
    return rank_up_list, runner_up_list


normala1, normala2 = normal_simulation(2)
normalb1, normalb2= normal_simulation(3)
normala_result1, normala_result2 = analyze_result(normala1, normala2)
normalb_result1, normalb_result2 = analyze_result(normalb1, normalb2)

print(f"昇級人数2, 3の差による次点の勝数の差")
for win_num in range(6, 11):
    print(f"{win_num:2d}勝: {normala_result2[win_num]}: {normalb_result2[win_num]}")

print(f"昇級人数2, 3の差による昇級確率の差")
for i, result in enumerate(zip(normala_result1, normalb_result1)):
    print(f"{i + 1:2d}位: {result[0]/100:.2f}: {result[1]/100:.2f}")

結果

昇級人数2, 3の差による次点の勝数の差
 6勝: 0: 0
 7勝: 12: 76
 8勝: 3996: 6696
 9勝: 5871: 3217
10勝: 121: 11

昇級3人だと50人でも次点8勝を2/3にできます。全勝4人以上の確率は0.1%。
昇級2人だと次点9勝が過半数になる。全勝3人以上の確率は1.2%。

昇級人数2, 3の差による昇級確率の差
 1位: 36.80: 45.84
 2位: 29.79: 40.48
 3位: 23.32: 34.48
 4位: 20.10: 29.40
 5位: 16.30: 25.33
 6位: 13.38: 20.16
 7位: 10.38: 17.13
 8位: 9.37: 14.65
 9位: 7.12: 12.44
10位: 6.03: 10.02
11位: 5.05: 8.45
12位: 4.06: 7.48
13位: 2.90: 5.49
14位: 3.06: 4.89
15位: 2.21: 4.69
16位: 1.74: 3.26
17位: 1.59: 2.95
18位: 1.21: 2.39
19位: 1.22: 2.00
20位: 0.90: 1.59
21位: 0.65: 1.38
22位: 0.69: 1.08
23位: 0.42: 0.96
24位: 0.30: 0.83
25位: 0.31: 0.45
26位: 0.21: 0.54
27位: 0.17: 0.41
28位: 0.21: 0.18
29位: 0.12: 0.29
30位: 0.07: 0.21
31位: 0.10: 0.19
32位: 0.06: 0.07
33位: 0.05: 0.06
34位: 0.01: 0.04
35位: 0.05: 0.09
36位: 0.03: 0.03
37位: 0.00: 0.01
38位: 0.00: 0.01
39位: 0.00: 0.01
40位: 0.00: 0.01
41位: 0.00: 0.00
42位: 0.01: 0.01
43位: 0.01: 0.01
44位: 0.00: 0.01
45位: 0.00: 0.00
46位: 0.00: 0.00
47位: 0.00: 0.00
48位: 0.00: 0.00
49位: 0.00: 0.00
50位: 0.00: 0.00

各順位で公平に昇級確率がアップしているように見えますが、
15~20位あたりに注目すると昇級確率が倍近くになってますね。

順位最下位に強いプレイヤーがいる場合

50位のレーティングを1位より200上としてシミュレーションを行った。

昇級人数2, 3の差による昇級確率の差
 1位: 28.56: 38.52
 2位: 22.64: 33.54
 3位: 18.32: 27.55
 4位: 15.39: 22.85
 5位: 12.41: 20.14
 6位: 10.74: 16.64
 7位: 8.03: 14.40
 8位: 7.11: 11.13
 9位: 5.67: 9.41
10位: 4.51: 7.92
11位: 3.83: 7.14
12位: 3.06: 5.51
13位: 2.61: 4.90
14位: 2.56: 3.77
15位: 2.11: 3.01
16位: 1.54: 2.83
17位: 1.24: 2.39
18位: 0.97: 1.94
19位: 0.90: 1.64
20位: 0.61: 1.10
21位: 0.50: 1.10
22位: 0.44: 1.00
23位: 0.29: 0.89
24位: 0.32: 0.71
25位: 0.19: 0.49
26位: 0.19: 0.30
27位: 0.12: 0.28
28位: 0.12: 0.18
29位: 0.13: 0.22
30位: 0.06: 0.15
31位: 0.04: 0.12
32位: 0.06: 0.06
33位: 0.04: 0.06
34位: 0.00: 0.06
35位: 0.01: 0.04
36位: 0.03: 0.04
37位: 0.00: 0.03
38位: 0.02: 0.01
39位: 0.03: 0.00
40位: 0.01: 0.04
41位: 0.00: 0.00
42位: 0.00: 0.01
43位: 0.01: 0.00
44位: 0.00: 0.01
45位: 0.00: 0.01
46位: 0.00: 0.00
47位: 0.00: 0.00
48位: 0.00: 0.01
49位: 0.00: 0.00
50位: 44.58: 57.85

リーグの最上位よりレーティング200強いぐらいではストレート昇級の確率は半々といえる。

降級点シミュレーション

  • 1位~49位までレーティング差10ずつ+50位だけ1位より200上の設定で行う。
  • 下位10(13)人を降級点としたときに降級点確率を10000回シミュレーションにより求める。

少しソースをいじるとできる。

# 順位戦シミュレーション 変数名はそのまま
def normal_simulation(rank_up_number: int):
    rank_up = []
    runner_up = []
    for x in range(simulation_number):
        league = League(player_number)
        for i in range(battle_number):
            league.random_match(i)
            league.battles(i)
        league.count_win()
        league.result_rank()
        rank_up.extend(league.result_rank_list[-rank_up_number:]) # 順位の末端を取得するようにする
        runner_up.append(league.players[league.result_rank_list[rank_up_number]].win)
        if x % 1000 == 0:
                print(x)
    return rank_up, runner_up
降級点人数10, 13の差による降級点確率の差
 1位: 0.04: 0.04
 2位: 0.03: 0.09
 3位: 0.03: 0.11
 4位: 0.05: 0.15
 5位: 0.10: 0.14
 6位: 0.06: 0.24
 7位: 0.15: 0.46
 8位: 0.07: 0.36
 9位: 0.14: 0.61
10位: 0.18: 0.62
11位: 0.40: 0.93
12位: 0.41: 1.25
13位: 0.50: 1.25
14位: 0.63: 1.62
15位: 0.85: 2.06
16位: 1.08: 2.19
17位: 1.49: 2.78
18位: 1.49: 3.20
19位: 1.84: 4.00
20位: 2.57: 4.92
21位: 2.89: 5.62
22位: 3.26: 6.92
23位: 4.17: 7.73
24位: 5.25: 9.40
25位: 5.71: 10.97
26位: 6.54: 12.64
27位: 8.43: 15.36
28位: 9.84: 17.78
29位: 10.74: 20.42
30位: 12.87: 23.53
31位: 14.95: 26.83
32位: 17.06: 29.69
33位: 20.22: 34.03
34位: 23.13: 37.53
35位: 26.65: 42.02
36位: 29.92: 46.37
37位: 33.39: 49.97
38位: 38.05: 54.68
39位: 42.89: 58.16
40位: 48.06: 62.14
41位: 53.06: 66.68
42位: 57.38: 69.88
43位: 62.80: 73.21
44位: 66.09: 74.72
45位: 70.04: 78.37
46位: 74.31: 81.08
47位: 77.96: 83.71
48位: 79.66: 86.38
49位: 82.57: 87.14
50位: 0.00: 0.02

3人増えただけで降級点確率が軒並み倍近くになってます。
下位はどうせ落ちるから上位がその分負担がかかるのですね。
上位の強豪が誰か死んでも全然おかしくない確率になっています。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0