6
6
from sgfmill import sgf
7
7
from scipy .stats import bernoulli
8
8
9
+
9
10
def spawn_process (command : "list[str]" ):
10
11
"""Spawn a process with the command and wait until the process ends.
11
12
@@ -18,59 +19,91 @@ def spawn_process(command: "list[str]"):
18
19
except Exception as e :
19
20
print (f"Error occurred: { str (e )} " )
20
21
22
+
21
23
def get_command (x ) -> str :
22
- command = f'{ x ["exe" ]} gtp -config { x ["config" ]} -model { x ["model" ]} -override-config maxVisits={ x ["maxVisits" ]} '
24
+ command = f'{ x ["exe" ]} gtp -config { x ["config" ]} -model { x ["model" ]} '
25
+ override_options = [
26
+ "maxVisits" ,
27
+ "suppressVirtualLossExploreFactor" ,
28
+ "suppressVirtualLossHindsight" ,
29
+ "suppressVirtualLossLeakCatchUp" ,
30
+ "numSearchThreads" ,
31
+ "useNoisePruning" ,
32
+ ]
33
+
34
+ for option in override_options :
35
+ if option in x :
36
+ command += f" -override-config { option } ={ x [option ]} "
37
+
23
38
return command
24
39
25
- def match (black_parameters , white_parameters , gogui_classpath , game_count , sgffile_prefix = "match" , verbose = True ) -> int :
40
+
41
+ def match (
42
+ black_parameters ,
43
+ white_parameters ,
44
+ gogui_classpath ,
45
+ game_count ,
46
+ sgffile_prefix = "match" ,
47
+ verbose = True ,
48
+ ) -> int :
26
49
black_command = get_command (black_parameters )
27
50
white_command = get_command (white_parameters )
28
51
board_size = 19
29
52
komi = 7.5
30
- twogtp = ['java' ,
31
- '-cp' ,
32
- gogui_classpath ,
33
- 'net.sf.gogui.tools.twogtp.Main' ,
34
- '-black' ,
35
- black_command ,
36
- '-white' ,
37
- white_command ,
38
- '-size' ,
39
- f'{ board_size } ' ,
40
- '-komi' ,
41
- f'{ komi } ' ,
42
- '-auto' ,
43
- '-sgffile' ,
44
- f'{ sgffile_prefix } -{ game_count } ' ]
53
+ twogtp = [
54
+ "java" ,
55
+ "-cp" ,
56
+ gogui_classpath ,
57
+ "net.sf.gogui.tools.twogtp.Main" ,
58
+ "-black" ,
59
+ black_command ,
60
+ "-white" ,
61
+ white_command ,
62
+ "-size" ,
63
+ f"{ board_size } " ,
64
+ "-komi" ,
65
+ f"{ komi } " ,
66
+ "-auto" ,
67
+ "-sgffile" ,
68
+ f"{ sgffile_prefix } -{ game_count } " ,
69
+ ]
45
70
46
71
spawn_process (twogtp )
47
- sgffile = f' { sgffile_prefix } -{ game_count } -0.sgf'
72
+ sgffile = f" { sgffile_prefix } -{ game_count } -0.sgf"
48
73
is_won = 0
49
74
50
75
with open (sgffile , "rb" ) as f :
51
76
sgf_string = f .read ()
52
77
game = sgf .Sgf_game .from_bytes (sgf_string )
53
78
winner = game .get_winner ()
54
79
55
- if ( winner == 'b' ) :
80
+ if winner == "b" :
56
81
# Black won
57
82
is_won = - 1
58
83
if verbose :
59
- print (f' Game { game_count } : Black won' )
60
- elif ( winner == 'w' ) :
84
+ print (f" Game { game_count } : Black won" )
85
+ elif winner == "w" :
61
86
# White won
62
87
is_won = 1
63
88
if verbose :
64
- print (f' Game { game_count } : White won' )
89
+ print (f" Game { game_count } : White won" )
65
90
else :
66
91
# Draw
67
92
is_won = 0
68
93
if verbose :
69
- print (f' Game { game_count } : Draw' )
94
+ print (f" Game { game_count } : Draw" )
70
95
71
96
return is_won
72
97
73
- def match_games (black_parameters , white_parameters , game_count_start , games , sgffile_prefix = "match" , verbose = True ) -> (int , int , int ):
98
+
99
+ def match_games (
100
+ black_parameters ,
101
+ white_parameters ,
102
+ game_count_start ,
103
+ games ,
104
+ sgffile_prefix = "match" ,
105
+ verbose = True ,
106
+ ) -> (int , int , int ):
74
107
results = []
75
108
game_count_stop = game_count_start + games
76
109
@@ -81,7 +114,8 @@ def match_games(black_parameters, white_parameters, game_count_start, games, sgf
81
114
"/Users/chinchangyang/Code/gogui/bin" ,
82
115
game_count ,
83
116
sgffile_prefix = sgffile_prefix ,
84
- verbose = verbose )
117
+ verbose = verbose ,
118
+ )
85
119
86
120
results .append (result )
87
121
@@ -94,6 +128,7 @@ def match_games(black_parameters, white_parameters, game_count_start, games, sgf
94
128
95
129
return (black_win , white_win , draw )
96
130
131
+
97
132
def elo (M : float , N : float ) -> float :
98
133
"""Calculate expected ELO
99
134
@@ -105,12 +140,13 @@ def elo(M: float, N: float) -> float:
105
140
float: expected ELO
106
141
"""
107
142
if N <= M :
108
- return float (' inf' )
143
+ return float (" inf" )
109
144
elif M <= 0 :
110
- return float (' -inf' )
145
+ return float (" -inf" )
111
146
else :
112
147
return - 400 * math .log10 (- 1 + (N / M ))
113
148
149
+
114
150
def elo_range (M : int , N : int , a : float ) -> float :
115
151
"""Calculate ELO standard deviation
116
152
@@ -122,9 +158,9 @@ def elo_range(M: int, N: int, a: float) -> float:
122
158
float: ELO standard deviation
123
159
"""
124
160
if N == M :
125
- return (float (' inf' ), float (' inf' ))
161
+ return (float (" inf" ), float (" inf" ))
126
162
elif M == 0 :
127
- return (float (' -inf' ), float (' -inf' ))
163
+ return (float (" -inf" ), float (" -inf" ))
128
164
else :
129
165
p = M / N # mean
130
166
var = bernoulli .var (p ) / N # variance of sample mean
@@ -134,70 +170,80 @@ def elo_range(M: int, N: int, a: float) -> float:
134
170
elo_negative_delta = elo (M - delta , N ) # ELO with negative delta
135
171
return (elo_negative_delta , elo_positive_delta )
136
172
173
+
137
174
if __name__ == "__main__" :
138
175
t0 = time .time ()
139
- bot_a_name = 'b18c384nbt'
176
+ bot_a_name = "K1e10-Hoff-LCUoff-T8-NPon"
140
177
141
178
bot_a_parameters = {
142
179
"exe" : "/Users/chinchangyang/Code/KataGo/cpp/build/katago" ,
143
180
"config" : "/Users/chinchangyang/.katago/default_gtp.cfg" ,
144
- "model" : "/Users/chinchangyang/Code/KataGo-Models/kata1-b18c384nbt-s7709731328-d3715293823.bin.gz" ,
145
- "maxVisits" : "2"
181
+ "model" : "/Users/chinchangyang/.katago/default_model.bin.gz" ,
182
+ "suppressVirtualLossExploreFactor" : "1e10" ,
183
+ "suppressVirtualLossHindsight" : "false" ,
184
+ "suppressVirtualLossLeakCatchUp" : "false" ,
185
+ "numSearchThreads" : "8" ,
186
+ "useNoisePruning" : "true" ,
146
187
}
147
188
148
- bot_b_name = 'b28c512nbt'
189
+ bot_b_name = "K8-Hoff-LCUoff-T4-NPoff"
149
190
150
191
bot_b_parameters = {
151
- "exe" : "/Users/chinchangyang/Code/KataGo-CCY/cpp/build/katago" ,
152
- "config" : "/Users/chinchangyang/Code/KataGo-CCY/cpp/configs/misc/coreml_example.cfg" ,
153
- "model" : "/Users/chinchangyang/Code/KataGo-Models/b28c512nbt-s1436726784-d3907069532.bin.gz" ,
154
- "maxVisits" : "2"
192
+ "exe" : "/Users/chinchangyang/Code/KataGo/cpp/build/katago" ,
193
+ "config" : "/Users/chinchangyang/.katago/default_gtp.cfg" ,
194
+ "model" : "/Users/chinchangyang/.katago/default_model.bin.gz" ,
195
+ "suppressVirtualLossExploreFactor" : "8" , # {4, 64}
196
+ "suppressVirtualLossHindsight" : "false" , # {false, true}
197
+ "suppressVirtualLossLeakCatchUp" : "false" , # {false, true}
198
+ "numSearchThreads" : "4" , # {8, 32}
199
+ "useNoisePruning" : "false" , # {false, true}
155
200
}
156
201
157
- total_games = 1024
202
+ total_games = 100
158
203
half_games = int (total_games / 2 )
159
204
160
205
black_win , white_win , draw = match_games (
161
- bot_a_parameters ,
162
- bot_b_parameters ,
163
- 0 ,
164
- half_games )
206
+ bot_a_parameters , bot_b_parameters , 0 , half_games
207
+ )
165
208
166
209
bot_a_win = black_win
167
210
bot_b_win = white_win
168
211
both_draw = draw
169
212
170
- print (f' { bot_a_name } Won: { bot_a_win } ' )
171
- print (f' { bot_b_name } Won: { bot_b_win } ' )
172
- print (f' Draw: { both_draw } ' )
213
+ print (f" { bot_a_name } Won: { bot_a_win } " )
214
+ print (f" { bot_b_name } Won: { bot_b_win } " )
215
+ print (f" Draw: { both_draw } " )
173
216
174
217
black_win , white_win , draw = match_games (
175
- bot_b_parameters ,
176
- bot_a_parameters ,
177
- half_games ,
178
- half_games )
218
+ bot_b_parameters , bot_a_parameters , half_games , half_games
219
+ )
179
220
180
221
bot_a_win = bot_a_win + white_win
181
222
bot_b_win = bot_b_win + black_win
182
223
both_draw = both_draw + draw
183
224
184
- print (f' { bot_a_name } Won: { bot_a_win } ' )
185
- print (f' { bot_b_name } Won: { bot_b_win } ' )
186
- print (f' Draw: { both_draw } ' )
225
+ print (f" { bot_a_name } Won: { bot_a_win } " )
226
+ print (f" { bot_b_name } Won: { bot_b_win } " )
227
+ print (f" Draw: { both_draw } " )
187
228
188
229
bot_a_outcome = bot_a_win + (both_draw / 2 )
189
230
bot_b_outcome = bot_b_win + (both_draw / 2 )
190
231
191
232
print (
192
- f'Expected ELO of { bot_a_name } parameters (from { total_games } games) = { elo (bot_a_outcome , total_games )} ' )
233
+ f"Expected ELO of { bot_a_name } parameters (from { total_games } games) = { elo (bot_a_outcome , total_games )} "
234
+ )
193
235
print (
194
- f'Expected ELO of { bot_b_name } parameters (from { total_games } games) = { elo (bot_b_outcome , total_games )} ' )
236
+ f"Expected ELO of { bot_b_name } parameters (from { total_games } games) = { elo (bot_b_outcome , total_games )} "
237
+ )
195
238
print (
196
- f'ELO range (+/- 1.0 standard deviation) of { bot_b_name } parameters = { elo_range (bot_b_outcome , total_games , 1.0 )} ' )
239
+ f"ELO range (+/- 1.0 standard deviation) of { bot_b_name } parameters = { elo_range (bot_b_outcome , total_games , 1.0 )} "
240
+ )
197
241
print (
198
- f'ELO range (+/- 2.0 standard deviation) of { bot_b_name } parameters = { elo_range (bot_b_outcome , total_games , 2.0 )} ' )
242
+ f"ELO range (+/- 2.0 standard deviation) of { bot_b_name } parameters = { elo_range (bot_b_outcome , total_games , 2.0 )} "
243
+ )
199
244
print (
200
- f'ELO range (+/- 3.0 standard deviation) of { bot_b_name } parameters = { elo_range (bot_b_outcome , total_games , 3.0 )} ' )
245
+ f"ELO range (+/- 3.0 standard deviation) of { bot_b_name } parameters = { elo_range (bot_b_outcome , total_games , 3.0 )} "
246
+ )
201
247
202
248
elapsed = time .time () - t0
203
- print (f' Elapsed: { str (datetime .timedelta (seconds = round (elapsed )))} ' )
249
+ print (f" Elapsed: { str (datetime .timedelta (seconds = round (elapsed )))} " )
0 commit comments