-
Notifications
You must be signed in to change notification settings - Fork 116
/
HACKING
375 lines (286 loc) · 14.9 KB
/
HACKING
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
This is brief developer-oriented overview of Pachi structure.
The aim of the software framework is to make it easy to plug your
engine to the common infrastructure and implement your ideas while
minimalizing the overhead of implementing the GTP, speed-optimized
board implementation, etc. Also, there are premade random playout
and UCT tree engines, so that you can directly tweak only particular
policies. The infrastructure is pretty fast and it should be quite
easy for you (or us) to extend it to provide more facilities for
your engine.
Pachi is completely Go-specific (c.f. Fuego; though e.g. atari go support
should be easy to add), but fairly modular. It has been built with focus
on MonteCarlo-based play, but it can in principle be used for other
play engines as well.
Basic architecture
==================
Pachi consists of the following components:
+------+ +--------+ +---------+
| core | -- | engine | -- | playout |
+------+ +--------+ +---------+
| | |
+-------------------+ +---------+
| modules |--| tactics |
| dcnn, patterns | +---------+
| joseki, ownermap |
+-------------------+
* "core" takes care of the program's lifetime, GTP interface and basic
fast Go board implementation
pachi.c global initialization and the main loop
version.h current version information
debug.h debugging infrastructure
random.[ch] fast random number generator
gtp.[ch] GTP protocol interface
network.[ch] Network interface (useful for distributed engine)
timeinfo.[ch] Time-keeping information
stone.[ch] one board point coloring definition
move.[ch] one board move definition
board.[ch] board definition and basic interface
gogui.[ch] gogui analyze commands
* "modules" provides extra functions like static tactical evaluation
and pattern matching; it is somewhat interwound with "core" component
mq.h "move queue" data structure
stats.h "move statistics" data structure
probdist.[ch] "probability distribution" data structure
ownermap.[ch] simulation-based finalpos. "owner map" data structure
fbook.[ch] fuseki database (opening book)
pattern3.[ch] fast 3x3 spatial pattern matcher
* "dcnn" manages neural networks for root node evaluation (policy network)
dcnn/dcnn.[ch] network loading and evaluation (c side)
dcnn/caffe.cpp network loading and evaluation (c++ side)
dcnn/dcnn_engine.c example "dcnn move generator" engine
dcnn/blunder.c filter out some obvious bad moves from dcnn output before
they get used in search to work around dcnn blind spots
dcnn/blunderscan.c internal engine for dcnn blunder debugging
* "pattern" mm pattern matcher provides priors to guide tree search
pattern/pattern.[ch] general multi-feature pattern matcher
pattern/spatial.[ch] spatial pattern matching
pattern/prob.[ch] pattern-based move predictor
pattern/pattern_engine.c example "mm patterns move generator" engine, used for testing / debugging
pattern/patternscan.c auxiliary engine used by mm pattern training pipeline
training/ mm training pipeline
patterns_mm.spat spatial patterns data
patterns_mm.gamma mm patterns gammas
* "joseki" provides joseki sequences to guide tree search when playing without dcnn
joseki/*.sgf joseki data
joseki19.gtp joseki data (as GTP stream)
joseki/joseki.[ch] pattern based joseki engine
joseki/joseki_engine.c "joseki move generator" engine used to visualize joseki data in gogui
joseki/josekiload.c load joseki data (internal engine)
* "josekifix" allows to override joseki moves that the dcnn plays poorly
josekifix/*.sgf joseki overrides (SGF file)
josekifix.gtp joseki overrides (as GTP stream)
josekifix/josekifix.[ch] pattern based joseki overrides matching
josekifix/josekifixload.c load override data (internal engine)
josekifix/fuseki.c choose initial fuseki
* "tactics" provides extended interfaces for the go board,
most important non-trivial tactical information
tactics/1lib.c dealing with 1-liberty groups (captures)
tactics/2lib.c dealing with 2-liberties groups
tactics/dragon.c recognizing connected groups
tactics/ladder.c ladder checker
tactics/nakade.c recognizing dead shapes
tactics/nlib.c dealing with n-liberties groups
tactics/seki.c handling sekis
tactics/selfatari.c distinguish between good / bad self-ataris
tactics/util.c board utils
* "engine" receives notifications about opponent moves and is asked
to generate a move to play on given board
engine.h abstract engine interface
uct/ the main UCT-player engine, see below
distributed/ "meta-engine" for distributed play by orchestrating
several UCT engines on different computers
other engines:
engines/external.c call external GTP engine
engines/random.c example "random move generator" engine
engines/replay.c example "playout move generator" engine
engines/montecarlo.c simple treeless Monte Carlo engine, quite bitrotten
* "playout" policy is asked to generate moves to play during the Monte Carlo
simulations, and to provide rough evaluation of moves feasibility for
the engine
playout.[ch] abstract playout policy interface,
Monte Carlo simulation execution
playout/light uniformly random playout policy
playout/moggy rule-based "Mogo-like" playout policy
* Also, several ways of testing Pachi are provided:
t-unit/ interface for writing unit-tests for specific
functionality, mainly tactics
t-play/ interface for testing performance by playing games
against a fixed opponent (e.g. GNUGo)
t-predict/ test prediction rates of various components
UCT architecture
================
The UCT engine (the proper name should be MCTS as it does not have that
much common with classic UCT now) has non-trivial structure by itself:
+-------------+ +-----+ +-------------------+
| node policy | -- | UCT | --- | node prior-hinter |
+-------------+ +-----+ +-------------------+
| |
+---------+ |
| playout | -----'
+---------+
* "UCT" is the core of the engine
uct.[ch] engine initialization, public interface
internal.h internal state and data structures
tree.[ch] minimax move tree with success statistics
walk.[ch] filling the tree by walking it many times
and running MC simulations from leaves
slave.[ch] engine interface for the distributed engine
* "node prior-hinter" assigns newly created nodes preliminary success
statistics ("prior values") to focus the search better
prior.[ch] variety of methods for setting the priors
(dcnn for root node, mm patterns for others)
* "node policy" mainly chooses the current node's child to descend
through during the tree walk, based on the already recorded statistics;
it must balance exploration and exploitation well during the selection
policy/ucb1 the old-school original simple policy
policy/ucb1amaf the AMAF/RAVE-based policy gathering statistics rapidly
* "dynkomi driver" dynamically determines self-imposed extra virtual komi
dynkomi.[ch]
UCT performance
===============
What's the cost of the different components, and where do the cpu cycles go ?
Here's the result of a performance analysis on Raspberry Pi with Pachi 12.70
to answer that question (see PERFS for details):
during tree search:
uct search takes 30% cpu time
leaving 70% for playouts.
if uct is now 100% and we break it down further:
priors represent 54% of that (pattern prior 40%)
ucb1amaf policy 38%
tree stuff etc 8%
UCT search modes
================
There are 4 main modes for move generation depending on client / options used:
mode typical clients gtp command uct options
------------------------------------------------------------------------------
genmove all genmove
genmove_analyze Lizzie, Sabaki lz-genmove_analyze
pondering all genmove pondering
analyze Lizzie, Sabaki lz-analyze
* genmove
this is the normal case: client sends "genmove" gtp command to ask engine
for a move, uct starts search in the foreground and stops when given time
or playouts requirements are met.
On kgs there's also "kgs-genmove_cleanup" command which is a special mode
entered when playing chinese and opponent doesn't agree on dead stones
(both players keep playing until all dead stones are removed)
* genmove_analyze
used by Lizzie, Sabaki etc to display fancy graphics during genmove
(gogui uses "gogui-livegfx" for that purpose). same as genmove but client uses
"lz-genmove_analyze" gtp command to get updates while search is going on.
* pondering
after genmove search continues in the background while opponent is thinking.
pondering stops at next "play" command.
* analyze (Lizzie, Sabaki)
client sends "lz-analyze" gtp command. no move is generated but search is
started in the background and updates sent to client in leela-zero format.
search stops when next gtp command is received.
There's also "pachi-genmoves" which is used by the distributed engine to start
search in the background and report state periodically.
Board Implementation
====================
The infrastructure is optimized for speed to make it well suited
for bruteforce engines, however tradeoffs are made to make it useful
for heavier MonteCarlo playouts as well (e.g. real liberties are
tracked instead of pseudoliberties). If you are looking for raw
light playout speed, libEGO is better choice.
In general, arbitrary board sizes are supported; however, board sizes
smaller than 9x9 have not been tested and board sizes larger than 25x25
are not supported by GTP - also, in theory some buffer overflows might
happen with board sizes larger than 19x19. The engine parameters are
primarily tuned for 19x19 play.
Ruleset
-------
While the Pachi engines generally play according to Chinese rules,
internally, Pachi uses Tromp-Taylor rules because they are simple,
fast and universal; they are very close to the New Zealand rules.
That means, it simply counts the number of stones and one-point eyes
of each color on the board, plus komi and handicap correction.
Tromp-Taylor rules also mean that multi-stone suicide is allowed! If you
do not like that (basically if you want to pretend it plays according
to Chinese rules), you need to rule that out in your engine, currently.
The provided engines DO avoid multi-stone suicide, though it is allowed
in the playouts for performance reasons (perhaps we should re-visit that
decision in light of heavy playouts).
Tromp-Taylor rules have positional superko; the board implementation
will set a flag if it is violated, but play the move anyway. You need
to enforce the superko rule in your engine.
GTP Implementation
==================
... should be better now, but has certainly not been written (or tested)
with security in mind. ENSURE that only trusted parties talk to Pachi's GTP
interface, as it totally non-resilient to any kind of overflow or bad input
attacks and allowing arbitrary input to be entered within is a major security
hole. Yes, this needs to be cleaned up.
Also, currently engines cannot plug in their own commands.
The final_status_list command requires engine support.
DCNN
====
dcnn/dcnn.c has the code that prepares the input planes from board state and
feeds that to caffe for dcnn evaluation (dcnn/caffe.cpp). If you want to use
a network with different inputs this is the place to accomodate it.
General Pattern Matcher
=======================
Pachi uses MM patterns to guide tree search. The pattern matcher runs on
the cpu each time a new node is explored. For each possible move it looks
for known spatial / tactical features and rates them according to learned
weights, which are obtained through supervised learning.
See pattern/README for details.
Plugin API
==========
The UCT engine allows external plugins to be loaded and provide external
knowledge for various heuristics - currently just biasing the MCTS priors,
but more can be added easily. The plugins should follow the API in
<uct/plugin.h> - see that file for details.
Joseki Database
===============
The joseki database is generated from variations of a SGF file. Josekis
patterns are matched based on spatial patterns: situation around previous
move and move to play must match (circle of 4 stones radius). See
joseki/README for details on how to generate the joseki database from sgf
files, and joseki.[ch] for the implementation. engines/josekiload.[ch] is
the aux engine for generating joseki patterns from gtp moves.
Opening Book
============
The UCT engine can "pre-read" the starting board position and
dump the core of the built tree to a file, loading it later. This is
called a 'tbook' (as in "tree book") and can be generated using the
tools/gentbook.sh script. The newly generated file is automatically
used by the UCT engine when found.
Alternatively, there is a support for directly used opening book
(so-called fbook, a.k.a. "forced book" or "fuseki book"). The book
is stored in a text file in Fuego-compatible format and can be loaded
using the ./pachi -f parameter. A naive way to build such a book
based on shell-based, twogtp-based UCT is available through the
tools/autobook/ framework.
Local Trees
===========
This is a mostly unique idea in Pachi, currently in development;
it does not work too well yet, but Pasky has great hopes for it in
the future.
A local tree is a tree comprising of (CFG-topologically) local
sequences, built in parallel with the real game tree; there is
a separate tree for black-first and white-first sequences. E.g if
the game tree (on empty board) consists of D4-C6-D6-Q16-O17-D7,
the coresponding local tree sequences are (black) D4-C6-D6, (white)
Q16-O17 and (white) D7. The simulation result is then recorded as
usual in the game tree, but also in the corresponding local trees.
The goal of this is to dynamically build a cache of various
resolutions of local situations. This is to overcome cases where
the proper resolution of a given situation is easily found in
the tree, but improper heuristical bisaes keep muddying the
evaluation down.
Exactly what kind of values to store in the local tree nodes is
still an open question. The original approach has been to simply
use simulation results directly or biased on base "value temperature";
now, we are experimenting with survival rate of the "base stone"
of the branch (the first move in the branch sequence). We also intend
to integrate criticality information with local tree data.
The local trees are descended in parallel with the main tree.
The values stored in local trees are added to the RAVE term
from the main tree during node selection. We also wish to use
the information from local trees in the simulations, but this is
still subject to research.
To enable local trees usage, pass local_tree=1 to the UCT engine.
There are many further knobs to twiddle, too.
Code is in local_tree branch.