├── .circleci ├── config.yml └── docker │ └── ubuntu_1804 │ └── Dockerfile ├── .clang-format ├── .flake8 ├── .gitignore ├── .gitmodules ├── CMakeLists.txt ├── CODE_OF_CONDUCT.rst ├── CONTRIBUTING.rst ├── Dockerfile ├── LICENSE ├── Makefile ├── README.rst ├── codetools ├── autoformat_cpp_style.sh ├── autoformat_py_style.sh ├── check_cpp_style.sh ├── check_py_style.sh ├── run_all_autoformatters.sh └── run_all_static_checks.sh ├── design_doc ├── ai_client.md ├── game_base.md ├── game_context.md ├── go_game.md ├── mcts.md ├── model_interface.md ├── options.md ├── record.md ├── sampler.md └── trainer.md ├── ladder_suite ├── ladder │ ├── 406844.sgf │ ├── 406958.sgf │ ├── 406959.sgf │ ├── 406996.sgf │ ├── 407143.sgf │ ├── 407203.sgf │ ├── 407214.sgf │ ├── 407248.sgf │ ├── 407302.sgf │ ├── 407354.sgf │ ├── 407364.sgf │ ├── 407384.sgf │ ├── 407399.sgf │ ├── 407401.sgf │ ├── 407482.sgf │ ├── 407493.sgf │ ├── 407521.sgf │ ├── 407523.sgf │ ├── 407541.sgf │ ├── 407542.sgf │ ├── 407559.sgf │ ├── 407570.sgf │ ├── 407578.sgf │ ├── 407581.sgf │ ├── 407882.sgf │ ├── 407999.sgf │ ├── 408042.sgf │ ├── 408129.sgf │ ├── 408137.sgf │ ├── 408140.sgf │ ├── 408156.sgf │ ├── 408179.sgf │ ├── 408185.sgf │ ├── 408188.sgf │ ├── 408231.sgf │ ├── 408234.sgf │ ├── 408331.sgf │ ├── 408345.sgf │ ├── 408350.sgf │ ├── 408361.sgf │ ├── 408489.sgf │ ├── 408551.sgf │ ├── 408584.sgf │ ├── 408726.sgf │ ├── 408774.sgf │ ├── 408777.sgf │ ├── 408815.sgf │ ├── 408824.sgf │ ├── 408866.sgf │ ├── 409200.sgf │ ├── 409219.sgf │ ├── 409252.sgf │ ├── 409279.sgf │ ├── 409355.sgf │ ├── 409377.sgf │ ├── 409399.sgf │ ├── 409445.sgf │ ├── 409477.sgf │ ├── 409563.sgf │ ├── 409598.sgf │ ├── 409600.sgf │ ├── 409608.sgf │ ├── 409643.sgf │ ├── 409806.sgf │ ├── 409826.sgf │ ├── 409848.sgf │ ├── 409856.sgf │ ├── 409867.sgf │ ├── 409993.sgf │ ├── 410034.sgf │ ├── 410217.sgf │ ├── 410333.sgf │ ├── 410605.sgf │ ├── 410615.sgf │ ├── 410756.sgf │ ├── 410807.sgf │ ├── 410818.sgf │ ├── 410991.sgf │ ├── 411061.sgf │ ├── 411072.sgf │ ├── 411087.sgf │ ├── 411099.sgf │ ├── 411106.sgf │ ├── 411203.sgf │ ├── 411228.sgf │ ├── 411295.sgf │ ├── 411342.sgf │ ├── 411435.sgf │ ├── 411482.sgf │ ├── 411518.sgf │ ├── 411565.sgf │ ├── 411578.sgf │ ├── 411644.sgf │ ├── 411670.sgf │ ├── 411851.sgf │ ├── 411881.sgf │ ├── 411899.sgf │ ├── 412038.sgf │ ├── 412092.sgf │ ├── 412141.sgf │ ├── 412181.sgf │ ├── 412280.sgf │ ├── 412313.sgf │ ├── 412407.sgf │ ├── 412432.sgf │ ├── 412440.sgf │ ├── 412477.sgf │ ├── 413022.sgf │ ├── 414239.sgf │ ├── 415297.sgf │ ├── 415304.sgf │ ├── 415520.sgf │ ├── 415643.sgf │ ├── 416911.sgf │ ├── 417459.sgf │ └── 417839.sgf ├── ladder_list └── ladder_magic_list ├── scripts ├── devmode_set_pythonpath.sh └── elfgames │ └── go │ ├── console_lib.py │ ├── df_console.py │ ├── gtp.sh │ ├── selfplay.py │ ├── server_addrs.py │ ├── start_client.sh │ ├── start_selfplay.sh │ ├── start_server.sh │ └── train.py ├── src_cpp ├── elf │ ├── CMakeLists.txt │ ├── Pybind.cc │ ├── Pybind.h │ ├── ai │ │ ├── ai.h │ │ └── tree_search │ │ │ ├── mcts.h │ │ │ ├── tree_search.h │ │ │ ├── tree_search_alg.h │ │ │ ├── tree_search_base.h │ │ │ ├── tree_search_node.h │ │ │ └── tree_search_options.h │ ├── base │ │ ├── common.h │ │ ├── context.h │ │ ├── ctrl.h │ │ ├── dispatcher.h │ │ ├── extractor.h │ │ ├── hist.h │ │ └── sharedmem.h │ ├── comm │ │ ├── broadcast.h │ │ ├── comm.h │ │ └── primitive.h │ ├── concurrency │ │ ├── ConcurrentQueue.h │ │ ├── Counter.cc │ │ ├── Counter.h │ │ └── TBBHashers.h │ ├── distributed │ │ ├── shared_reader.h │ │ ├── shared_replay_buffer.h │ │ ├── shared_rw_buffer2.h │ │ └── zmq_util.h │ ├── legacy │ │ ├── pybind_helper.h │ │ └── python_options_utils_cpp.h │ ├── logging │ │ ├── IndexedLoggerFactory.cc │ │ ├── IndexedLoggerFactory.h │ │ ├── Levels.cc │ │ ├── Levels.h │ │ ├── Pybind.cc │ │ └── Pybind.h │ ├── options │ │ ├── OptionMap.cc │ │ ├── OptionMap.h │ │ ├── OptionMapTest.cc │ │ ├── OptionSpec.cc │ │ ├── OptionSpec.h │ │ ├── OptionSpecTest.cc │ │ ├── OptionSpecTest.h │ │ ├── Pybind.cc │ │ └── Pybind.h │ ├── pybind_module.cc │ └── utils │ │ ├── json_utils.h │ │ ├── member_check.h │ │ └── utils.h └── elfgames │ └── go │ ├── CMakeLists.txt │ ├── README.md │ ├── base │ ├── board.cc │ ├── board.h │ ├── board_feature.cc │ ├── board_feature.h │ ├── common.cc │ ├── common.h │ ├── go_common.h │ ├── go_state.cc │ ├── go_state.h │ ├── hash_num.h │ └── test │ │ ├── board_feature_test.cc │ │ ├── coord_test.cc │ │ ├── go_test.cc │ │ ├── symmetry_test.cc │ │ └── test_utils.h │ ├── common │ ├── dispatcher_callback.h │ ├── game_base.h │ ├── game_feature.h │ ├── game_selfplay.cc │ ├── game_selfplay.h │ ├── game_stats.h │ ├── game_utils.h │ ├── go_game_specific.h │ ├── go_state_ext.cc │ ├── go_state_ext.h │ ├── model_pair.h │ ├── notifier.h │ └── record.h │ ├── inference │ ├── Pybind.cc │ ├── Pybind.h │ ├── game_context.h │ └── pybind_module.cc │ ├── mcts │ ├── ai.h │ ├── mcts.h │ └── mcts_test.cc │ ├── sgf │ ├── sgf.cc │ ├── sgf.h │ └── sgf_test.cc │ └── train │ ├── Pybind.cc │ ├── Pybind.h │ ├── client_manager.cc │ ├── client_manager.h │ ├── ctrl_eval.h │ ├── ctrl_selfplay.h │ ├── ctrl_utils.h │ ├── data_loader.h │ ├── distri_base.h │ ├── distri_client.h │ ├── distri_server.h │ ├── fair_pick.h │ ├── game_context.h │ ├── game_ctrl.h │ ├── game_train.cc │ ├── game_train.h │ └── pybind_module.cc ├── src_py ├── elf │ ├── __init__.py │ ├── context_utils.py │ ├── logging │ │ ├── __init__.py │ │ └── configuration.py │ ├── more_labels.py │ ├── options │ │ ├── __init__.py │ │ ├── import_options.py │ │ ├── py_option_map.py │ │ └── py_option_spec.py │ ├── utils_elf.py │ └── zmq_util.py ├── elfgames │ └── go │ │ ├── df_model.py │ │ ├── df_model2.py │ │ ├── df_model3.py │ │ ├── game.py │ │ ├── game_inference.py │ │ ├── mcts_prediction.py │ │ └── multiple_prediction.py └── rlpytorch │ ├── README.md │ ├── __init__.py │ ├── methods │ ├── __init__.py │ ├── actor_critic.py │ ├── discounted_reward.py │ ├── policy_gradient.py │ ├── q_learning.py │ ├── rnn_actor_critic.py │ ├── utils.py │ └── value_matcher.py │ ├── model_base.py │ ├── model_interface.py │ ├── model_loader.py │ ├── runner │ ├── __init__.py │ ├── eval_iters.py │ ├── multi_process.py │ ├── parameter_server.py │ └── single_process.py │ ├── sampler │ ├── __init__.py │ ├── sample_methods.py │ └── sampler.py │ ├── stats │ ├── __init__.py │ └── stats.py │ ├── trainer │ ├── __init__.py │ ├── lstm_trainer.py │ ├── timer.py │ ├── trainer.py │ └── utils.py │ └── utils │ ├── __init__.py │ ├── fp16_utils.py │ ├── hist_states.py │ ├── size_utils.py │ └── utils.py └── third_party └── CMakeLists.txt /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | jobs: 4 | build_and_test_1804: 5 | resource_class: xlarge 6 | docker: 7 | - image: pytorch/elf:ci_ubuntu_1804 8 | steps: 9 | - checkout 10 | - run: 11 | name: submodules 12 | command: | 13 | git submodule sync 14 | git submodule update --init --recursive 15 | - run: 16 | name: cpp_style 17 | command: ./codetools/check_cpp_style.sh 18 | - run: 19 | name: python_style 20 | command: ./codetools/check_py_style.sh 21 | - run: 22 | name: compile 23 | command: make clean all VERBOSE=1 24 | - run: 25 | name: cpp_tests 26 | command: make test_cpp 27 | - run: 28 | name: python_tests 29 | command: "true" 30 | 31 | workflows: 32 | version: 2 33 | build_and_test_1804: 34 | jobs: 35 | - build_and_test_1804 36 | -------------------------------------------------------------------------------- /.circleci/docker/ubuntu_1804/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:bionic 2 | 3 | WORKDIR /tmp/docker_init 4 | SHELL ["/bin/bash", "-c"] 5 | 6 | RUN apt-get update 7 | RUN apt-get install -y \ 8 | clang-format \ 9 | clang-tidy \ 10 | cmake \ 11 | curl \ 12 | g++ \ 13 | gcc \ 14 | git \ 15 | libboost-all-dev \ 16 | libzmq3-dev \ 17 | ; 18 | RUN ln -sf `which clang-format-6.0` /usr/bin/clang-format 19 | RUN curl https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh > conda_install.sh 20 | RUN bash conda_install.sh -p /conda -b 21 | ENV PATH=/conda/bin:${PATH} 22 | RUN conda update -n base conda 23 | RUN conda create -yn elf_env python=3.6 24 | RUN source activate elf_env 25 | RUN conda install -y \ 26 | flake8 \ 27 | numpy \ 28 | pytest \ 29 | zeromq \ 30 | ; 31 | RUN conda install -c conda-forge autopep8 32 | RUN conda install -c pytorch pytorch torchvision cuda90 33 | 34 | RUN rm -rf /tmp/docker_init 35 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | AccessModifierOffset: -1 3 | AlignAfterOpenBracket: AlwaysBreak 4 | AlignConsecutiveAssignments: false 5 | AlignConsecutiveDeclarations: false 6 | AlignEscapedNewlinesLeft: true 7 | AlignOperands: false 8 | AlignTrailingComments: false 9 | AllowAllParametersOfDeclarationOnNextLine: false 10 | AllowShortBlocksOnASingleLine: false 11 | AllowShortCaseLabelsOnASingleLine: false 12 | AllowShortFunctionsOnASingleLine: Empty 13 | AllowShortIfStatementsOnASingleLine: false 14 | AllowShortLoopsOnASingleLine: false 15 | AlwaysBreakAfterReturnType: None 16 | AlwaysBreakBeforeMultilineStrings: true 17 | AlwaysBreakTemplateDeclarations: true 18 | BinPackArguments: false 19 | BinPackParameters: false 20 | BraceWrapping: 21 | AfterClass: false 22 | AfterControlStatement: false 23 | AfterEnum: false 24 | AfterFunction: false 25 | AfterNamespace: false 26 | AfterObjCDeclaration: false 27 | AfterStruct: false 28 | AfterUnion: false 29 | BeforeCatch: false 30 | BeforeElse: false 31 | IndentBraces: false 32 | BreakBeforeBinaryOperators: None 33 | BreakBeforeBraces: Attach 34 | BreakBeforeTernaryOperators: true 35 | BreakConstructorInitializersBeforeComma: false 36 | ColumnLimit: 80 37 | CommentPragmas: '^ IWYU pragma:' 38 | ConstructorInitializerAllOnOneLineOrOnePerLine: true 39 | ConstructorInitializerIndentWidth: 4 40 | ContinuationIndentWidth: 4 41 | Cpp11BracedListStyle: true 42 | DerivePointerAlignment: false 43 | DisableFormat: false 44 | ForEachMacros: [ FOR_EACH_RANGE, FOR_EACH, ] 45 | IncludeCategories: 46 | - Regex: '^<.*\.h(pp)?>' 47 | Priority: 1 48 | - Regex: '^<.*' 49 | Priority: 2 50 | - Regex: '.*' 51 | Priority: 3 52 | IndentCaseLabels: true 53 | IndentWidth: 2 54 | IndentWrappedFunctionNames: false 55 | KeepEmptyLinesAtTheStartOfBlocks: false 56 | MacroBlockBegin: '' 57 | MacroBlockEnd: '' 58 | MaxEmptyLinesToKeep: 1 59 | NamespaceIndentation: None 60 | ObjCBlockIndentWidth: 2 61 | ObjCSpaceAfterProperty: false 62 | ObjCSpaceBeforeProtocolList: false 63 | PenaltyBreakBeforeFirstCallParameter: 1 64 | PenaltyBreakComment: 300 65 | PenaltyBreakFirstLessLess: 120 66 | PenaltyBreakString: 1000 67 | PenaltyExcessCharacter: 1000000 68 | PenaltyReturnTypeOnItsOwnLine: 200 69 | PointerAlignment: Left 70 | ReflowComments: true 71 | SortIncludes: true 72 | SpaceAfterCStyleCast: false 73 | SpaceBeforeAssignmentOperators: true 74 | SpaceBeforeParens: ControlStatements 75 | SpaceInEmptyParentheses: false 76 | SpacesBeforeTrailingComments: 1 77 | SpacesInAngles: false 78 | SpacesInContainerLiterals: true 79 | SpacesInCStyleCastParentheses: false 80 | SpacesInParentheses: false 81 | SpacesInSquareBrackets: false 82 | Standard: Cpp11 83 | TabWidth: 8 84 | UseTab: Never 85 | ... 86 | -------------------------------------------------------------------------------- /.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | exclude = 3 | __init__.py 4 | __pycache__, 5 | .git, 6 | build, 7 | experimental, 8 | third_party, 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Build and interpreter artifacts 2 | *.a 3 | *.bin 4 | *.dSYM 5 | *.o 6 | *.pyc 7 | *.so 8 | build/ 9 | __pycache__/ 10 | 11 | # Random junk 12 | *.sw? 13 | *.db 14 | *.json 15 | *.swo 16 | *.tree 17 | .codemod.bookmark 18 | .nfs* 19 | tmp*.sh 20 | tags 21 | build/ 22 | save_dir*/ 23 | test-*/ 24 | Testing/ 25 | pachi-*/ 26 | experimental/patterns.prob 27 | experimental/patterns.spat 28 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "third_party/concurrentqueue"] 2 | path = third_party/concurrentqueue 3 | url = https://github.com/cameron314/concurrentqueue.git 4 | [submodule "third_party/pybind11"] 5 | path = third_party/pybind11 6 | url = https://github.com/pybind/pybind11.git 7 | [submodule "third_party/spdlog"] 8 | path = third_party/spdlog 9 | url = https://github.com/gabime/spdlog.git 10 | [submodule "third_party/json"] 11 | path = third_party/json 12 | url = https://github.com/nlohmann/json.git 13 | [submodule "third_party/googletest"] 14 | path = third_party/googletest 15 | url = https://github.com/google/googletest.git 16 | [submodule "third_party/tbb"] 17 | path = third_party/tbb 18 | url = https://github.com/01org/tbb.git 19 | ignore = untracked 20 | [submodule "third_party/cppzmq"] 21 | path = third_party/cppzmq 22 | url = https://github.com/zeromq/cppzmq.git 23 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.3) 2 | 3 | # Basic third-party dependencies 4 | 5 | find_package(Threads) 6 | 7 | #find_package(Boost REQUIRED COMPONENTS 8 | # thread 9 | #) 10 | #include_directories(${Boost_INCLUDE_DIR}) 11 | 12 | # Include third-party dependencies 13 | 14 | add_subdirectory( 15 | third_party 16 | ${CMAKE_CURRENT_BINARY_DIR}/third_party) 17 | find_package(TBB REQUIRED tbb) # Need to find_package in parent scope 18 | 19 | # Sanity checks 20 | 21 | if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") 22 | # require at least gcc 7.1 23 | if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.1) 24 | message(FATAL_ERROR "GCC version must be at least 7.1!") 25 | endif() 26 | endif() 27 | 28 | # Variables from Git 29 | 30 | execute_process(COMMAND git rev-parse HEAD 31 | OUTPUT_VARIABLE GIT_COMMIT_HASH) 32 | string(STRIP ${GIT_COMMIT_HASH} GIT_COMMIT_HASH) 33 | execute_process(COMMAND git diff-index --quiet HEAD -- 34 | RESULT_VARIABLE GIT_UNSTAGED) 35 | if(${GIT_UNSTAGED}) 36 | set(GIT_STAGED_STRING unstaged) 37 | else() 38 | set(GIT_STAGED_STRING staged) 39 | endif() 40 | 41 | # Global compiler config 42 | 43 | set(CMAKE_CXX_STANDARD 17) 44 | set(PYBIND11_CPP_STANDARD -std=c++17) 45 | set(CMAKE_CXX_FLAGS 46 | "${CMAKE_CXX_FLAGS} -Wall -Werror -Wextra -Wno-register -Wno-deprecated-declarations -fPIC -march=native") 47 | set(CMAKE_CXX_FLAGS_RELEASE "-O3") 48 | if(NOT CMAKE_BUILD_TYPE) 49 | set(CMAKE_BUILD_TYPE Release) 50 | endif() 51 | 52 | # Define a convenience function for tests 53 | function(add_cpp_tests prefix lib_to_link) 54 | set(test_list ${ARGV}) 55 | list(REMOVE_AT test_list 0) 56 | list(REMOVE_AT test_list 0) 57 | foreach(test_file ${test_list}) 58 | string(REPLACE "/" "_" test_name ${test_file}) 59 | string(REPLACE ".cc" "" test_name ${test_name}) 60 | string(CONCAT test_name ${prefix} ${test_name}) 61 | add_executable(${test_name} ${test_file}) 62 | add_test(${test_name} ${test_name}) 63 | target_link_libraries(${test_name} ${lib_to_link} gtest) 64 | endforeach(test_file) 65 | endfunction(add_cpp_tests) 66 | 67 | # Include everything in src_cpp 68 | 69 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src_cpp/) 70 | 71 | # Main ELF library 72 | 73 | add_subdirectory( 74 | src_cpp/elf 75 | ${CMAKE_CURRENT_BINARY_DIR}/elf) 76 | 77 | # ELF games 78 | 79 | add_subdirectory( 80 | src_cpp/elfgames/go 81 | ${CMAKE_CURRENT_BINARY_DIR}/elfgames/go) 82 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.rst: -------------------------------------------------------------------------------- 1 | =============== 2 | Code of Conduct 3 | =============== 4 | 5 | Facebook has adopted a Code of Conduct that we expect project participants to adhere to. Please read the `full text`__ so that you can understand what actions will and will not be tolerated. 6 | 7 | __ https://code.fb.com/codeofconduct/ 8 | -------------------------------------------------------------------------------- /CONTRIBUTING.rst: -------------------------------------------------------------------------------- 1 | =================== 2 | Contributing to ELF 3 | =================== 4 | 5 | We want to make contributing to this project as easy and transparent as possible. 6 | 7 | Dependencies 8 | ============ 9 | 10 | In addition to the project dependencies, you'll need the following if you'd like to contribute code to ELF2:: 11 | 12 | sudo apt-get install clang-format clang-tidy 13 | conda install flake8 pytest 14 | conda install -c conda-forge autopep8 15 | 16 | Pull Requests 17 | ============= 18 | 19 | We actively welcome your pull requests. 20 | 21 | 1. Fork the repo and create your branch from ``master``. 22 | 2. If you've added code that should be tested, add tests. 23 | 3. If you've changed APIs, update the documentation. 24 | 4. Ensure the test suite passes. 25 | 5. Make sure your code lints (see the ``codetools/`` directory). 26 | 6. If you haven't already, complete the Contributor License Agreement ("CLA"). 27 | 28 | We have a continuous integration system that will double-check steps 4 and 5 for you. 29 | 30 | Contributor License Agreement ("CLA") 31 | ===================================== 32 | 33 | In order to accept your pull request, we need you to submit a CLA. You only need 34 | to do this once to work on any of Facebook's open source projects. 35 | 36 | Complete your CLA `here`__. 37 | 38 | __ https://code.facebook.com/cla 39 | 40 | Issues 41 | ====== 42 | 43 | We use GitHub issues to track public bugs. Please ensure your description is 44 | clear and has sufficient instructions to be able to reproduce the issue. 45 | 46 | This project is still an extremely unstable prototype so we will be limited in 47 | the amount of support we're able to provide. 48 | 49 | Coding Style 50 | ============ 51 | 52 | - For C++, we use a style very similar to the `HHVM style guide`__. This prescription is not formal, and our ``.clang-format`` file and existing code should eventually be a good source of truth. Due to a quirk of ``Python.h``, all ``pybind`` includes must be first in the include order. 53 | - For Python, we use pep8. 54 | 55 | __ https://github.com/facebook/hhvm/blob/master/hphp/doc/coding-conventions.md 56 | 57 | We have tools to check your C++ and Python code in the ``codetools/`` directory 58 | 59 | License 60 | ======= 61 | 62 | By contributing to ELF, you agree that your contributions will be licensed 63 | under the LICENSE file in the root directory of this source tree. 64 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD License 2 | 3 | For ELF software 4 | 5 | Copyright (c) 2018-present, Facebook, Inc. All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without modification, 8 | are permitted provided that the following conditions are met: 9 | 10 | * Redistributions of source code must retain the above copyright notice, this 11 | list of conditions and the following disclaimer. 12 | 13 | * Redistributions in binary form must reproduce the above copyright notice, 14 | this list of conditions and the following disclaimer in the documentation 15 | and/or other materials provided with the distribution. 16 | 17 | * Neither the name Facebook nor the names of its contributors may be used to 18 | endorse or promote products derived from this software without specific 19 | prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 22 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 25 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 28 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all 2 | all: elf elfgames/go 3 | 4 | .PHONY: clean 5 | clean: 6 | rm -rf build/ 7 | 8 | .PHONY: test 9 | test: test_cpp 10 | 11 | .PHONY: test_cpp 12 | test_cpp: test_cpp_elf test_cpp_elfgames_go 13 | 14 | build/Makefile: CMakeLists.txt */CMakeLists.txt 15 | mkdir -p build 16 | (cd build && cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ..) 17 | 18 | .PHONY: elf 19 | elf: build/Makefile 20 | (cd build && cmake --build elf -- -j) 21 | 22 | .PHONY: test_cpp_elf 23 | test_cpp_elf: 24 | (cd build/elf && GTEST_COLOR=1 ctest --output-on-failure) 25 | 26 | .PHONY: test_cpp_elfgames_go 27 | test_cpp_elfgames_go: 28 | (cd build/elfgames/go && GTEST_COLOR=1 ctest --output-on-failure) 29 | 30 | .PHONY: elfgames/go 31 | elfgames/go: build/Makefile 32 | (cd build && cmake --build elfgames/go -- -j) 33 | -------------------------------------------------------------------------------- /codetools/autoformat_cpp_style.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # cd to parent of script's directory (i.e. project root) 4 | cd "${0%/*}"/.. 5 | 6 | find . -type f \( -name '*.h' -o -name '*.cc' \) \ 7 | -not -path './.git/*' \ 8 | -not -path './build/*' \ 9 | -not -path './experimental/*' \ 10 | -not -path './third_party/*' \ 11 | -exec clang-format -i {} + 12 | -------------------------------------------------------------------------------- /codetools/autoformat_py_style.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # cd to parent of script's directory (i.e. project root) 4 | cd "${0%/*}"/.. 5 | 6 | find . -type f \( -name '*.py' \) \ 7 | -not -path './.git/*' \ 8 | -not -path './build/*' \ 9 | -not -path './experimental/*' \ 10 | -not -path './third_party/*' \ 11 | -exec autopep8 -i {} + 12 | -------------------------------------------------------------------------------- /codetools/check_cpp_style.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # cd to parent of script's directory (i.e. project root) 4 | cd "${0%/*}"/.. 5 | 6 | if [ -z "${DIFF_CMD}" ]; then 7 | if diff --color /dev/null /dev/null > /dev/null 2>&1; then 8 | DIFF_CMD='diff --color -U5 ' 9 | elif colordiff /dev/null /dev/null > /dev/null 2>&1; then 10 | DIFF_CMD='colordiff -U5 ' 11 | else 12 | DIFF_CMD='diff -U5 ' 13 | fi 14 | fi 15 | 16 | CLANG_FORMAT_CMD=${CLANG_FORMAT_CMD:=clang-format} 17 | OUTPUT=${OUTPUT:=/dev/null} 18 | FILES=$( \ 19 | find . -type f \( -name '*.h' -o -name '*.cc' \) \ 20 | -not -path './.git/*' \ 21 | -not -path './build/*' \ 22 | -not -path './experimental/*' \ 23 | -not -path './third_party/*' \ 24 | ) 25 | 26 | MUST_FORMAT=0 27 | for f in ${FILES}; 28 | do 29 | if ! test -e ${f}; then 30 | continue 31 | fi 32 | diff -q ${f} <(${CLANG_FORMAT_CMD} -style=file ${f}) > ${OUTPUT} 33 | if test $? -ne 0; 34 | then 35 | echo '=========== C++ style error (fix with clang-format) =============' 36 | echo ${f} is not properly formatted. Diff of correction: 37 | echo '-----------------------------------------------------------------' 38 | MUST_FORMAT=1 39 | ${CLANG_FORMAT_CMD} -style=file ${f} > /tmp/$(basename $f) 40 | ${DIFF_CMD} $f /tmp/$(basename $f) 41 | echo 42 | echo 43 | echo 44 | fi 45 | done 46 | 47 | exit ${MUST_FORMAT} 48 | -------------------------------------------------------------------------------- /codetools/check_py_style.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # cd to parent of script's directory (i.e. project root) 4 | cd "${0%/*}"/.. 5 | 6 | flake8 . 7 | -------------------------------------------------------------------------------- /codetools/run_all_autoformatters.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # cd to parent of script's directory (i.e. project root) 4 | cd "${0%/*}"/.. 5 | 6 | ./codetools/autoformat_cpp_style.sh 7 | ./codetools/autoformat_py_style.sh 8 | -------------------------------------------------------------------------------- /codetools/run_all_static_checks.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # cd to parent of script's directory (i.e. project root) 4 | cd "${0%/*}"/.. 5 | 6 | ./codetools/check_cpp_style.sh 7 | ./codetools/check_py_style.sh 8 | -------------------------------------------------------------------------------- /design_doc/game_base.md: -------------------------------------------------------------------------------- 1 | # Game Base Interface 2 | 3 | ## Go Game Base: 4 | - class GoGameBase is the base class, from which selfplay and training mode classes are derived 5 | - public members: 6 | ```cpp 7 | mainLoop() // while client doesn't stop game, act(); 8 | virtual act()=0; 9 | ``` 10 | - private members: 11 | ```cpp 12 | GameClient* client_; 13 | rng; 14 | _options; 15 | _context_options; 16 | ``` 17 | 18 | ## Go Game Self Play 19 | - class ``GoGameSelfPlay`` derived from GoGameBase 20 | - Public Members: 21 | ```cpp 22 | // get ai, board feature, ai.act(), Bind State to Functions, send and wait; make diverse move; mcts update info; forward(c); terminate and finish game if needed; 23 | act(); 24 | 25 | showBoard() 26 | GoStateExt _state_ext 27 | EvalCtrl* eval_ctrl_ 28 | unique_ptr _ai, _ai2; 29 | unique_ptr _human_player; 30 | ``` 31 | - private members: 32 | ```cpp 33 | init_ai() 34 | mcts_make_diverse_move() 35 | mcts_update_info() 36 | 37 | restart() 38 | ``` 39 | - provided Python interface: 40 | ```python 41 | class GoGameSelfplay() 42 | def showBoard() 43 | def getNextPlayer() 44 | def getLastMove() 45 | def getScore() 46 | def getLastScore() 47 | ``` 48 | 49 | ## Go Game Train 50 | - class ``GoGameSelfPlay`` derived from GoGameBase 51 | - Public members: 52 | ```cpp 53 | // get sampler, sample, randomly pick move from record, setD4Code(), BindStateToFunctions("train") 54 | act(); 55 | ``` -------------------------------------------------------------------------------- /design_doc/model_interface.md: -------------------------------------------------------------------------------- 1 | # Model Interface in ELF 2 | 3 | ## Model Interface 4 | - class ModelInterface is a python class saving network models. 5 | - Its member `models` is a k-v store to call a CNN model by name. 6 | ```python 7 | class ModelInterface(object): 8 | def __init__(self, option_map): 9 | self.option_map = option_map 10 | self.models = {} 11 | self.old_models = deque() 12 | self.optimizers = {} 13 | 14 | def clone(self, gpu=None): 15 | # return a deep copy of self 16 | 17 | def __contains__(self, key): 18 | # overload the "in" operator 19 | 20 | def add_model(self, key, model, ...): 21 | # add a model to self.models[key] 22 | 23 | def update_model(self, key, model): 24 | # reload model parameter from a state_dict 25 | 26 | def remove_model(self, key): 27 | # delete a model by key 28 | 29 | def average_model(self, key, model): 30 | # average self.models[key] and model 31 | 32 | def copy(self, dst_key, src_key): 33 | # copy self.model[src_key] to self.model[dst_key] 34 | 35 | def zero_grad(self): 36 | # zero_grad items in self.optimizers 37 | 38 | def __get__item(self, key): 39 | # Get an item associated with ``key`` from self.models 40 | ``` -------------------------------------------------------------------------------- /design_doc/options.md: -------------------------------------------------------------------------------- 1 | # ELF Option Parser and Interface 2 | 3 | Since ELF Go project has a lot of options, we have a separate folding to manage and implement options in both C++ and python. 4 | 5 | ## Design of Option 6 | - Basically in the folder src_cpp/elf/options/ and src_py/elf/options/; 7 | - Important classes like **game**, **model**, **trainer**, **evaluator**, **sampler** and so forth; 8 | 9 | ## Option Spec Class (Python) 10 | - All arguments from command line are parsed by argparser in py_option_spec.py 11 | - class **PyOptionSpec** does the parsing; 12 | - Inheritted from class **OptionSpec** in C++; 13 | - After doing the parsing, **parse()** will convert the parsed arguments to a Option Map class. 14 | 15 | ## Option Map Class (Python) 16 | - A class to handle Argument by Json shared info between python and C++; 17 | - class **PyOptionMap** receives a **PyOptionSpec** class and saves as a member; 18 | - Inherited from class **OptionMap** in C++; 19 | 20 | ## 3. Detailed Design 21 | - class OptionSpec (C++) 22 | ```cpp 23 | class OptionSpec { 24 | public: 25 | bool addOption(string optionName, string help) 26 | bool addOption(string optionName, string help, T defaultValue) 27 | vector getOptionNames(): get all option names as a vector; 28 | json **getPythonArgparseOptionsAsJSON()** wrap everything up in a json array; 29 | string getPythonArgparseOptionsAsJSONString() 30 | addPrefixSuffixToOptionNames(string prefix, string suffix) 31 | 32 | private: 33 | const OptionBase& getOptionInfo() 34 | unordered_map> optionSpecMap_; 35 | } 36 | ``` 37 | -------------------------------------------------------------------------------- /design_doc/sampler.md: -------------------------------------------------------------------------------- 1 | # Sampler in ELF 2 | 3 | Python class in src_py/rlpytorch/sampler/ folder. It is a little out-of-date and not realy used in the Go project. 4 | 5 | ## Class Sampler 6 | - Used to sample an action from policy. 7 | - In ELF-Go, MCTS and sampling move is integrated together in C++, so this part of codes are not actually used. 8 | ```python 9 | class Sampler(object): 10 | def __init__(self, option_map): 11 | self.sample_nodes = [] 12 | 13 | def sample(self, state_curr): 14 | # Sample an action from distribution using a certain sample method 15 | # method could be epsilon_greedy or multinomial 16 | ``` 17 | 18 | ## Sampler Methods 19 | - Sample with check: 20 | ```python 21 | def sample_with_check(probs, greedy=False): 22 | 23 | def sample_eps_with_check(probs, epsilon, greedy=False): 24 | ``` 25 | - Two sample methods provided based on numpy: 26 | ```python 27 | import numpy 28 | 29 | def uniform_multinomial(batchsize, num_action, use_cuda=True): 30 | 31 | def epsilon_greedy(state_curr, args, node="pi"): 32 | ``` -------------------------------------------------------------------------------- /design_doc/trainer.md: -------------------------------------------------------------------------------- 1 | # Trainer and Evaluation in ELF 2 | 3 | ## Evaluator 4 | - class Evaluator is a pure python class, which run neural network in eval mode and get return results and update some stat info 5 | ```python 6 | class Evaluator(object): 7 | def __init__(self, option_map, name, ...): 8 | 9 | def setup(self, mi=None, sampler=None): 10 | self.mi = mi 11 | self.sampler = sampler 12 | 13 | if self.stats is not None: 14 | self.stats.reset() 15 | 16 | def episode_start(self, i): 17 | self.actor_count = 0 18 | 19 | def actor(self, batch): 20 | # get model form self.mi, set volatile=True 21 | # forward() 22 | # feed_batch() to update self.stats 23 | # return reply_msg 24 | 25 | def episode_summary(self, i): 26 | # called after each episode 27 | ``` 28 | 29 | ## Trainer 30 | - Trainer is also a pure python class wrapped on evaluator. 31 | ```python 32 | class Trainer(object): 33 | def __init__(self, option_map, ...): 34 | self.saver = ModelSaver(option_map) 35 | self.counter = MultiCounter() # in utils.py 36 | self.evaluator = Evaluator() 37 | 38 | def setup(self, rl_method, mi, sampler): 39 | self.mi = mi 40 | self.sampler = sampler 41 | self.rl_method = rl_method 42 | 43 | def actor(self, batch): 44 | # run eval mode 45 | 46 | def train(self, batch, *args, **kwargs): 47 | mi = self.evaluator.mi 48 | mi.zero_grad() 49 | # call update() mcts_prediction.py 50 | res = self.rl_method.update(mi, batch, stats) 51 | ``` 52 | -------------------------------------------------------------------------------- /ladder_suite/ladder/406996.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[xia_169]PB[Zen-15.7-1c0g]WR[3580?]BR[3219]DT[2018-04-04]PC[(CGOS) 19x19 Computer Go Server]RE[B+Time]GN[406996] 4 | ;B[pd]BL[895];W[dd]WL[896];B[qp]BL[893];W[dp]WL[892];B[fq]BL[888];W[op]WL[888];B[cn]BL[882];W[fp]WL[884] 5 | ;B[gp]BL[878];W[fo]WL[880];B[dq]BL[877];W[gq]WL[877];B[eq]BL[872];W[hp]WL[873];B[go]BL[867];W[hq]WL[868] 6 | ;B[cp]BL[860];W[gn]WL[864];B[ho]BL[856];W[do]WL[860];B[co]BL[854];W[cq]WL[857];B[fn]BL[847];W[en]WL[853] 7 | ;B[fm]BL[842];W[io]WL[849];B[hn]BL[841];W[hm]WL[845];B[in]BL[835];W[em]WL[841];B[eo]BL[831];W[ep]WL[837] 8 | ;B[dn]BL[826];W[eo]WL[833];B[el]BL[820];W[dm]WL[830];B[dl]BL[816];W[bm]WL[826];B[cm]BL[810];W[nf]WL[822] 9 | ;B[pf]BL[799];W[nj]WL[817];B[cf]BL[789];W[df]WL[814];B[dg]BL[783];W[cg]WL[809];B[be]BL[778];W[ce]WL[805] 10 | ;B[bf]BL[772];W[bd]WL[801];B[cc]BL[771];W[cd]WL[798];B[ef]BL[769];W[de]WL[794];B[ch]BL[767];W[eg]WL[790] 11 | ;B[dh]BL[765];W[ff]WL[786];B[eh]BL[750];W[ee]WL[782];B[mq]BL[735];W[kq]WL[778];B[oq]BL[722];W[pq]WL[774] 12 | ;B[pp]BL[715];W[nq]WL[770];B[or]BL[708];W[nr]WL[766];B[np]BL[702];W[oo]WL[762];B[mr]BL[698];W[pr]WL[758] 13 | ;B[ns]BL[690];W[qq]WL[754];B[rq]BL[677];W[rp]WL[750];B[ro]BL[664];W[qo]WL[745];B[sp]BL[662]) 14 | 15 | -------------------------------------------------------------------------------- /ladder_suite/ladder/407384.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[xia_169]PB[leela-vega]WR[3575?]BR[3500]DT[2018-04-04]PC[(CGOS) 19x19 Computer Go Server]RE[B+Resign]GN[407384] 4 | ;B[pq]BL[887];W[dd]WL[896];B[cc]BL[875];W[dc]WL[892];B[cd]BL[869];W[cf]WL[889];B[ce]BL[863];W[de]WL[885] 5 | ;B[bf]BL[860];W[dp]WL[882];B[pc]BL[850];W[cb]WL[877];B[bb]BL[845];W[bg]WL[873];B[df]BL[841];W[cg]WL[869] 6 | ;B[db]BL[840];W[eb]WL[866];B[ca]BL[839];W[ef]WL[862];B[cq]BL[835];W[cp]WL[858];B[dq]BL[833];W[fq]WL[855] 7 | ;B[eq]BL[828];W[ep]WL[851];B[fr]BL[825];W[bq]WL[848];B[br]BL[822];W[gr]WL[844];B[fp]BL[814];W[gq]WL[839] 8 | ;B[bp]BL[812];W[bo]WL[836];B[aq]BL[807];W[fo]WL[832];B[pf]BL[799];W[pp]WL[827];B[qq]BL[787];W[op]WL[824] 9 | ;B[qp]BL[782];W[oq]WL[820];B[pn]BL[780];W[qh]WL[816];B[gp]BL[774];W[qo]WL[812];B[qn]BL[768];W[ro]WL[808] 10 | ;B[po]BL[763];W[rn]WL[804];B[rm]BL[760];W[rl]WL[801];B[qm]BL[758];W[ql]WL[797];B[sl]BL[752];W[hp]WL[793] 11 | ;B[go]BL[747];W[sk]WL[789];B[sm]BL[742];W[fn]WL[786];B[ho]BL[736];W[ip]WL[782];B[gm]BL[732];W[fm]WL[778] 12 | ;B[gl]BL[730];W[fl]WL[774];B[gk]BL[729];W[io]WL[771];B[dg]BL[724];W[dh]WL[766];B[eg]BL[719];W[fh]WL[763] 13 | ;B[fg]BL[714];W[gg]WL[759];B[ff]BL[709];W[gf]WL[755];B[fe]BL[704];W[eh]WL[751];B[ge]BL[702];W[he]WL[747] 14 | ;B[hd]BL[698];W[gd]WL[744];B[fd]BL[694];W[gc]WL[740];B[fc]BL[693];W[id]WL[736];B[hc]BL[688];W[gb]WL[732] 15 | ;B[ie]BL[681];W[hf]WL[728];B[ic]BL[679];W[jd]WL[724];B[jc]BL[676];W[kc]WL[721];B[kb]BL[672];W[ld]WL[716] 16 | ;B[lb]BL[667];W[fb]WL[712];B[ec]BL[663];W[da]WL[709];B[ea]BL[658];W[jb]WL[705];B[ib]BL[653];W[ee]WL[701] 17 | ;B[ed]BL[649];W[hb]WL[697];B[ja]BL[644];W[ia]WL[693];B[ha]BL[639];W[ga]WL[690];B[fa]BL[631];W[rp]WL[685] 18 | ;B[rq]BL[626];W[pr]WL[681];B[qr]BL[622];W[qs]WL[677];B[rs]BL[616];W[rr]WL[674];B[ps]BL[609];W[sq]WL[670] 19 | ;B[or]BL[602];W[ss]WL[666];B[sr]BL[598];W[si]WL[662];B[fk]BL[590];W[ek]WL[658];B[ej]BL[585];W[dj]WL[654] 20 | ;B[gh]BL[577];W[gi]WL[650];B[hh]BL[573];W[hi]WL[646];B[ih]BL[569];W[ii]WL[642];B[jh]BL[565];W[ji]WL[638] 21 | ;B[kh]BL[561];W[ki]WL[634];B[lh]BL[555];W[if]WL[630];B[je]BL[548];W[jf]WL[626];B[ke]BL[541];W[kf]WL[622] 22 | ;B[le]BL[536];W[lf]WL[618];B[me]BL[533];W[mf]WL[614];B[ng]BL[529];W[nf]WL[610];B[og]BL[526];W[mh]WL[606] 23 | ;B[mg]BL[522];W[lg]WL[602];B[li]BL[517];W[mi]WL[598];B[lj]BL[511];W[mj]WL[594];B[lk]BL[505];W[mk]WL[590] 24 | ;B[ll]BL[498];W[ml]WL[586];B[lm]BL[491];W[mm]WL[582];B[im]BL[486];W[jm]WL[578];B[jl]BL[482];W[il]WL[573] 25 | ;B[ik]BL[476];W[jk]WL[569];B[hl]BL[472];W[kl]WL[565];B[jn]BL[467];W[il]WL[561];B[in]BL[463];W[gn]WL[557] 26 | ;B[hn]BL[459];W[kn]WL[553];B[km]BL[454];W[jl]WL[549];B[jo]BL[451];W[ko]WL[545];B[jp]BL[448];W[kp]WL[541] 27 | ;B[jq]BL[444];W[kq]WL[537];B[jj]BL[438];W[kj]WL[533];B[kk]BL[435];W[is]WL[529];B[jr]BL[430];W[js]WL[525] 28 | ;B[kr]BL[425];W[lr]WL[521];B[ks]BL[421];W[mq]WL[517];B[qe]BL[415];W[lp]WL[513];B[bn]BL[409]) 29 | 30 | -------------------------------------------------------------------------------- /ladder_suite/ladder/407581.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[xia_169]PB[Zen-15.7-1c0g]WR[3507?]BR[3220]DT[2018-04-05]PC[(CGOS) 19x19 Computer Go Server]RE[B+Time]GN[407581] 4 | ;B[pd]BL[895];W[dd]WL[896];B[qp]BL[892];W[dp]WL[892];B[fq]BL[887];W[op]WL[888];B[cn]BL[881];W[fp]WL[884] 5 | ;B[gp]BL[877];W[fo]WL[881];B[dq]BL[876];W[gq]WL[877];B[eq]BL[870];W[hp]WL[874];B[go]BL[865];W[hq]WL[868] 6 | ;B[cp]BL[858];W[gn]WL[864];B[ho]BL[853];W[do]WL[860];B[co]BL[851];W[cq]WL[857];B[fn]BL[845];W[en]WL[853] 7 | ;B[fm]BL[840];W[io]WL[849];B[hn]BL[838];W[hm]WL[845];B[in]BL[833];W[em]WL[841];B[eo]BL[829];W[ep]WL[838] 8 | ;B[dn]BL[824];W[eo]WL[834];B[el]BL[818];W[dm]WL[830];B[dl]BL[814];W[cm]WL[826];B[bm]BL[813];W[cl]WL[822] 9 | ;B[ck]BL[808];W[bl]WL[819];B[bk]BL[806];W[al]WL[814];B[ak]BL[802];W[jn]WL[810];B[am]BL[793];W[im]WL[806] 10 | ;B[jo]BL[786];W[ko]WL[802];B[ip]BL[780];W[jp]WL[798];B[io]BL[767];W[jq]WL[795];B[kn]BL[760];W[ln]WL[791] 11 | ;B[jm]BL[752];W[km]WL[787];B[jn]BL[737];W[lo]WL[783];B[pq]BL[722];W[oq]WL[779];B[qn]BL[717];W[pp]WL[775] 12 | ;B[qq]BL[707];W[qo]WL[772];B[ro]BL[699];W[po]WL[768];B[rm]BL[690];W[rp]WL[764];B[or]BL[671];W[so]WL[760] 13 | ;B[rn]BL[665];W[rq]WL[756];B[rr]BL[658];W[qr]WL[752];B[pr]BL[655];W[rs]WL[748];B[qs]BL[647];W[sr]WL[745] 14 | ;B[ss]BL[637];W[nf]WL[741];B[nq]BL[624];W[rs]WL[737];B[qr]BL[615];W[nr]WL[733];B[mr]BL[608];W[os]WL[729] 15 | ;B[ns]BL[601];W[ms]WL[724];B[ls]BL[595];W[mq]WL[720];B[np]BL[588];W[lh]WL[715];B[lm]BL[582];W[mm]WL[711] 16 | ;B[kl]BL[577];W[gi]WL[707];B[ml]BL[571];W[ha]WL[703];B[nc]BL[565];W[hf]WL[699];B[kc]BL[559];W[ll]WL[695] 17 | ;B[lk]BL[553];W[fk]WL[691];B[pf]BL[547];W[eh]WL[686];B[oh]BL[541];W[mf]WL[682];B[mi]BL[535];W[oa]WL[677] 18 | ;B[pb]BL[530];W[rh]WL[673];B[rf]BL[507];W[be]WL[668];B[hc]BL[502];W[ag]WL[663];B[ec]BL[497];W[pk]WL[659] 19 | ;B[mh]BL[491];W[ai]WL[654];B[dc]BL[486];W[ob]WL[650];B[oc]BL[481];W[ka]WL[645];B[ib]BL[476];W[ia]WL[641] 20 | ;B[jb]BL[471];W[cb]WL[637];B[cc]BL[465];W[cf]WL[632];B[bd]BL[460];W[ie]WL[629];B[fe]BL[456];W[qh]WL[625] 21 | ;B[rk]BL[451]) 22 | 23 | -------------------------------------------------------------------------------- /ladder_suite/ladder/408179.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[shang_cfa]PB[ngo-1.1.1]WR[3603]BR[3290]DT[2018-04-06]PC[(CGOS) 19x19 Computer Go Server]RE[B+Illegal]GN[408179] 4 | ;B[dp]BL[892];W[pd]WL[896];B[qp]BL[886];W[dd]WL[892];B[qf]BL[880];W[op]WL[888];B[nc]BL[872];W[nd]WL[884] 5 | ;B[md]BL[866];W[ne]WL[881];B[pc]BL[866];W[mc]WL[877];B[oc]BL[858];W[ld]WL[874];B[me]BL[851];W[lc]WL[869] 6 | ;B[qd]BL[849];W[mf]WL[865];B[le]BL[841];W[pe]WL[861];B[qe]BL[835];W[ke]WL[857];B[lf]BL[828];W[mg]WL[853] 7 | ;B[lg]BL[826];W[lh]WL[849];B[jf]BL[823];W[mh]WL[846];B[je]BL[822];W[jd]WL[841];B[id]BL[815];W[ic]WL[838] 8 | ;B[hd]BL[815];W[hc]WL[834];B[gc]BL[814];W[kd]WL[830];B[jg]BL[811];W[gd]WL[826];B[gb]BL[810];W[fd]WL[823] 9 | ;B[jc]BL[802];W[jb]WL[819];B[ib]BL[802];W[kc]WL[815];B[hb]BL[802];W[jc]WL[812];B[ec]BL[802];W[dc]WL[807] 10 | ;B[eb]BL[798];W[ed]WL[803];B[hf]BL[791];W[fc]WL[799];B[fb]BL[786];W[db]WL[795];B[mb]BL[786];W[lb]WL[791] 11 | ;B[ka]BL[785];W[nb]WL[787];B[ja]BL[778];W[ea]WL[784];B[ia]BL[771];W[fa]WL[779];B[ob]BL[765];W[ma]WL[776] 12 | ;B[oa]BL[765];W[ga]WL[772];B[na]BL[761];W[jh]WL[768];B[la]BL[755];W[ie]WL[764];B[he]BL[748];W[kg]WL[760] 13 | ;B[kf]BL[741];W[if]WL[756];B[ig]BL[734];W[ha]WL[753];B[da]BL[727];W[ha]WL[749];B[cb]BL[720];W[ea]WL[745] 14 | ;B[fa]BL[714];W[bb]WL[741];B[cc]BL[708];W[ca]WL[737];B[ba]BL[701];W[aa]WL[733];B[bc]BL[694];W[ca]WL[729] 15 | ;B[ce]BL[691];W[cd]WL[725];B[bd]BL[684];W[be]WL[721];B[bf]BL[678];W[cf]WL[717];B[de]BL[673];W[df]WL[713] 16 | ;B[ee]BL[667];W[fe]WL[709];B[ef]BL[662];W[ff]WL[705];B[eg]BL[662];W[fg]WL[701];B[eh]BL[662];W[fh]WL[697] 17 | ;B[ei]BL[658];W[fi]WL[693];B[ej]BL[656];W[ad]WL[689];B[ae]BL[650];W[ac]WL[685];B[ab]BL[644];W[ac]WL[681] 18 | ;B[kh]BL[638];W[ad]WL[677];B[ab]BL[638];C[KO attempted] 19 | ) 20 | 21 | -------------------------------------------------------------------------------- /ladder_suite/ladder/408489.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[Zen-15.9-1c1g]PB[qin_ehh]WR[3610]BR[3820?]DT[2018-04-06]PC[(CGOS) 19x19 Computer Go Server]RE[W+Resign]GN[408489] 4 | ;B[dp]BL[896];W[pc]WL[894];B[pp]BL[892];W[cd]WL[890];B[qe]BL[888];W[pi]WL[887];B[od]BL[885];W[oc]WL[883] 5 | ;B[nd]BL[881];W[mc]WL[882];B[ec]BL[877];W[qn]WL[873];B[pk]BL[873];W[nq]WL[867];B[np]BL[869];W[mp]WL[862] 6 | ;B[no]BL[865];W[qq]WL[861];B[qp]BL[862];W[pq]WL[856];B[mq]BL[858];W[oq]WL[852];B[lp]BL[854];W[mo]WL[846] 7 | ;B[lq]BL[849];W[op]WL[843];B[mn]BL[846];W[lo]WL[838];B[oo]BL[842];W[po]WL[833];B[ko]BL[838];W[ln]WL[827] 8 | ;B[lm]BL[834];W[kn]WL[822];B[pn]BL[830];W[qo]WL[817];B[qm]BL[826];W[pm]WL[810];B[jn]BL[822];W[km]WL[804] 9 | ;B[kl]BL[819];W[jm]WL[799];B[im]BL[816];W[jl]WL[796];B[jk]BL[812];W[il]WL[789];B[hl]BL[809];W[ik]WL[785] 10 | ;B[ij]BL[805];W[hk]WL[779];B[gk]BL[802];W[hj]WL[772];B[hi]BL[798];W[gj]WL[767];B[fj]BL[795];W[gi]WL[761] 11 | ;B[gh]BL[791];W[fi]WL[756];B[ei]BL[787];W[fh]WL[751];B[fg]BL[783];W[eh]WL[746];B[dh]BL[779];W[eg]WL[742] 12 | ;B[ef]BL[775];W[dg]WL[739];B[cg]BL[771];W[df]WL[737];B[de]BL[767];W[cf]WL[734]) 13 | 14 | -------------------------------------------------------------------------------- /ladder_suite/ladder/408584.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[qin_ehh]PB[Pangu-127-n]WR[3781?]BR[3702]DT[2018-04-06]PC[(CGOS) 19x19 Computer Go Server]RE[B+Resign]GN[408584] 4 | ;B[dp]BL[899];W[dd]WL[896];B[pq]BL[883];W[pd]WL[892];B[qf]BL[879];W[po]WL[888];B[qo]BL[863];W[qn]WL[885] 5 | ;B[qp]BL[863];W[pn]WL[881];B[nc]BL[856];W[pf]WL[877];B[pg]BL[850];W[of]WL[873];B[qd]BL[849];W[qg]WL[869] 6 | ;B[qe]BL[843];W[ph]WL[866];B[og]BL[838];W[qh]WL[861];B[pc]BL[837];W[nd]WL[858];B[od]BL[831];W[ng]WL[854] 7 | ;B[oh]BL[825];W[oi]WL[850];B[nh]BL[819];W[mh]WL[847];B[ni]BL[813];W[oc]WL[843];B[ob]BL[806];W[nj]WL[838] 8 | ;B[mi]BL[801];W[li]WL[835];B[mj]BL[796];W[mk]WL[832];B[lj]BL[791];W[kj]WL[828];B[lk]BL[787];W[ll]WL[825] 9 | ;B[kk]BL[785]) 10 | 11 | -------------------------------------------------------------------------------- /ladder_suite/ladder/408774.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[Pangu-127-n]PB[qin_ehh]WR[3683]BR[3820?]DT[2018-04-07]PC[(CGOS) 19x19 Computer Go Server]RE[W+Resign]GN[408774] 4 | ;B[pd]BL[896];W[dp]WL[898];B[pp]BL[892];W[dd]WL[890];B[fq]BL[888];W[cn]WL[884];B[fc]BL[885];W[cf]WL[876] 5 | ;B[dc]BL[881];W[cc]WL[870];B[cb]BL[877];W[ec]WL[870];B[db]BL[873];W[ed]WL[869];B[eb]BL[869];W[qq]WL[865] 6 | ;B[qp]BL[865];W[pq]WL[861];B[nq]BL[862];W[oq]WL[860];B[op]BL[859];W[nr]WL[859];B[fd]BL[855];W[qc]WL[852] 7 | ;B[pc]BL[850];W[qd]WL[852];B[qf]BL[847];W[qe]WL[852];B[pe]BL[844];W[rf]WL[851];B[qb]BL[840];W[rb]WL[851] 8 | ;B[re]BL[837];W[pb]WL[835];B[rc]BL[832];W[qa]WL[835];B[rd]BL[829];W[qb]WL[835];B[rg]BL[825];W[pf]WL[834] 9 | ;B[qg]BL[821];W[oe]WL[834];B[of]BL[818];W[pg]WL[833];B[ne]BL[814];W[nc]WL[831];B[od]BL[809];W[ph]WL[828] 10 | ;B[qi]BL[806];W[ng]WL[823];B[ld]BL[800];W[me]WL[817];B[mf]BL[796];W[le]WL[810];B[md]BL[792];W[nd]WL[803] 11 | ;B[ke]BL[789];W[lf]WL[796];B[lg]BL[785];W[kf]WL[790];B[jf]BL[782];W[kg]WL[786];B[kh]BL[778];W[jg]WL[784] 12 | ;B[ig]BL[774];W[jh]WL[781];B[ji]BL[771];W[ih]WL[779];B[hh]BL[767];W[ii]WL[779];B[ij]BL[762];W[hi]WL[777] 13 | ;B[gi]BL[759];W[hj]WL[775];B[nb]BL[755];W[ob]WL[767];B[mc]BL[750];W[oc]WL[761];B[hk]BL[746];W[gj]WL[760] 14 | ;B[fj]BL[743];W[gk]WL[759];B[gl]BL[739];W[fk]WL[759]) 15 | 16 | -------------------------------------------------------------------------------- /ladder_suite/ladder/408824.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[LZ-b3b00c-t1-v3200]PB[zhou-dgj]WR[3037]BR[3470]DT[2018-04-07]PC[(CGOS) 19x19 Computer Go Server]RE[W+Time]GN[408824] 4 | ;B[pd]BL[896];W[dp]WL[897];B[pp]BL[892];W[dd]WL[894];B[nc]BL[888];W[qq]WL[891];B[pq]BL[884];W[qp]WL[890] 5 | ;B[qn]BL[881];W[qo]WL[887];B[po]BL[877];W[rn]WL[887];B[qr]BL[874];W[rr]WL[886];B[ro]BL[871];W[pr]WL[883] 6 | ;B[rq]BL[866];W[qs]WL[882];B[rp]BL[862];W[qr]WL[882];B[rm]BL[859];W[pn]WL[881];B[qm]BL[855];W[nq]WL[880] 7 | ;B[on]BL[850];W[pm]WL[878];B[np]BL[846];W[mp]WL[875];B[pl]BL[842];W[om]WL[873];B[nm]BL[838];W[ol]WL[871] 8 | ;B[mq]BL[835];W[oo]WL[869];B[lp]BL[831];W[mo]WL[867];B[nn]BL[827];W[no]WL[865];B[ok]BL[823];W[nl]WL[863] 9 | ;B[ml]BL[819];W[nk]WL[862];B[nj]BL[816];W[mk]WL[862];B[lk]BL[813];W[mj]WL[861];B[mi]BL[809];W[lj]WL[861] 10 | ;B[kj]BL[806];W[li]WL[861];B[lh]BL[802];W[ki]WL[860];B[ji]BL[799];W[kh]WL[859];B[kg]BL[795];W[jh]WL[859] 11 | ;B[ih]BL[792];W[jg]WL[858];B[jf]BL[788];W[ig]WL[858];B[hg]BL[784];W[if]WL[857];B[ie]BL[780];W[hf]WL[857] 12 | ;B[gf]BL[776];W[he]WL[856];B[hd]BL[772];W[ge]WL[856];B[fe]BL[769];W[gd]WL[855];B[gc]BL[764];W[fd]WL[855] 13 | ;B[ed]BL[760];W[fc]WL[855];B[ec]BL[756];W[fb]WL[854];B[lo]BL[751];W[ii]WL[851];B[mn]BL[746];W[op]WL[850] 14 | ;B[oq]BL[743];W[or]WL[848];B[po]BL[739];W[jj]WL[845];B[kk]BL[735];W[ln]WL[841];B[kn]BL[731];W[mm]WL[838] 15 | ;B[lm]BL[727];W[ee]WL[834];B[de]BL[723];W[ff]WL[833];B[cd]BL[720];W[dc]WL[830];B[cc]BL[716];W[db]WL[828] 16 | ;B[cb]BL[712];W[df]WL[824];B[ce]BL[708];W[cf]WL[822];B[bf]BL[704];W[bg]WL[820];B[be]BL[700];W[ip]WL[818] 17 | ;B[mn]BL[697];W[in]WL[815];B[nm]BL[693];W[cn]WL[811];B[on]BL[689];W[nn]WL[808];B[mm]BL[685];W[jm]WL[805] 18 | ;B[km]BL[681];W[jo]WL[803];B[ko]BL[677];W[kl]WL[800];B[jk]BL[673];W[jl]WL[798];B[ik]BL[670];W[ll]WL[795] 19 | ;B[jn]BL[666];W[im]WL[793];B[io]BL[662];W[ho]WL[790];B[jp]BL[658];W[jq]WL[789];B[io]BL[654];W[kq]WL[787] 20 | ;B[hp]BL[650];W[jo]WL[786];B[iq]BL[647];W[kp]WL[782];B[go]BL[643];W[hq]WL[779];B[gp]BL[639];W[ir]WL[776] 21 | ;B[hn]BL[635];W[io]WL[774];B[ns]BL[631];W[em]WL[770];B[lq]BL[627];W[mr]WL[766];B[lr]BL[624];W[nr]WL[764] 22 | ;B[js]BL[620];W[kr]WL[761];B[ks]BL[616];W[ms]WL[758];B[ls]BL[612];W[is]WL[755];B[hr]BL[609];W[gq]WL[752] 23 | ;B[gr]BL[605];W[fq]WL[750];B[hs]BL[601];W[jr]WL[746];B[gs]BL[597];W[ch]WL[742];B[hl]BL[593];W[ln]WL[738] 24 | ;B[js]BL[590];W[ql]WL[735];B[ko]BL[586];W[rl]WL[732];B[lm]BL[582];W[qf]WL[728];B[kn]BL[578];W[qd]WL[725] 25 | ;B[gn]BL[574];W[pc]WL[722];B[bm]BL[570];W[bn]WL[718];B[rf]BL[565];W[pe]WL[714];B[ei]BL[560];W[lc]WL[711] 26 | ;B[qb]BL[556];W[pb]WL[708];B[nb]BL[552];W[od]WL[704];B[cj]BL[548];W[ek]WL[701];B[rd]BL[544];W[re]WL[698] 27 | ) 28 | 29 | -------------------------------------------------------------------------------- /ladder_suite/ladder/408866.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[han_gaf]PB[Zen-15.9-1c1g]WR[3831?]BR[3608]DT[2018-04-07]PC[(CGOS) 19x19 Computer Go Server]RE[B+Resign]GN[408866] 4 | ;B[pd]BL[895];W[pp]WL[896];B[dc]BL[888];W[dp]WL[892];B[cn]BL[884];W[de]WL[888];B[fq]BL[877];W[fp]WL[884] 5 | ;B[gp]BL[876];W[fo]WL[880];B[dq]BL[875];W[gq]WL[877];B[eq]BL[871];W[hp]WL[873];B[go]BL[866];W[hq]WL[869] 6 | ;B[cp]BL[863];W[do]WL[865];B[co]BL[859];W[gn]WL[861];B[ho]BL[854];W[jo]WL[857];B[io]BL[849];W[in]WL[854] 7 | ;B[ip]BL[844];W[iq]WL[850];B[jp]BL[839];W[kp]WL[846];B[jq]BL[834]) 8 | 9 | -------------------------------------------------------------------------------- /ladder_suite/ladder/409200.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[Pangu-127-n]PB[qin_ehh]WR[3681]BR[3775]DT[2018-04-07]PC[(CGOS) 19x19 Computer Go Server]RE[W+Resign]GN[409200] 4 | ;B[pp]BL[896];W[dd]WL[898];B[dp]BL[892];W[pd]WL[891];B[qf]BL[888];W[nc]WL[884];B[qd]BL[884];W[qc]WL[878] 5 | ;B[rc]BL[881];W[qe]WL[878];B[rd]BL[877];W[pe]WL[877];B[re]BL[873];W[cq]WL[873];B[dq]BL[869];W[cp]WL[873] 6 | ;B[cn]BL[866];W[co]WL[872];B[do]BL[862];W[bn]WL[872];B[pf]BL[859];W[qq]WL[871];B[qp]BL[854];W[pq]WL[871] 7 | ;B[nq]BL[851];W[oq]WL[871];B[op]BL[847];W[nr]WL[870];B[rq]BL[844];W[rr]WL[870];B[or]BL[840];W[rp]WL[862] 8 | ;B[qr]BL[836];W[sq]WL[861];B[pr]BL[832];W[rq]WL[861];B[mr]BL[829];W[np]WL[860];B[mq]BL[825];W[qm]WL[858] 9 | ;B[no]BL[819];W[mp]WL[851];B[qn]BL[815];W[rn]WL[850];B[ro]BL[812];W[so]WL[842];B[lp]BL[808];W[mo]WL[835] 10 | ;B[mn]BL[804];W[lo]WL[828];B[qo]BL[801];W[rl]WL[823];B[ko]BL[797];W[ln]WL[816];B[sn]BL[794];W[sm]WL[808] 11 | ;B[lm]BL[789];W[kn]WL[804];B[jn]BL[785];W[km]WL[801];B[kl]BL[782];W[jm]WL[798];B[im]BL[778];W[jl]WL[797] 12 | ;B[jk]BL[775];W[il]WL[796];B[hl]BL[772];W[ik]WL[796];B[ij]BL[768];W[hk]WL[795]) 13 | 14 | -------------------------------------------------------------------------------- /ladder_suite/ladder/409219.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[Pangu-127-n]PB[han_gaf]WR[3682]BR[3820?]DT[2018-04-07]PC[(CGOS) 19x19 Computer Go Server]RE[W+Resign]GN[409219] 4 | ;B[pd]BL[896];W[dp]WL[898];B[dd]BL[892];W[pp]WL[891];B[qn]BL[889];W[nq]WL[884];B[qf]BL[885];W[cc]WL[877] 5 | ;B[cd]BL[881];W[dc]WL[871];B[fc]BL[877];W[ec]WL[871];B[ed]BL[874];W[fb]WL[870];B[bc]BL[871];W[bb]WL[870] 6 | ;B[eb]BL[867];W[db]WL[863];B[gb]BL[864];W[ea]WL[862];B[gc]BL[858];W[cn]WL[853];B[dm]BL[854];W[dn]WL[837] 7 | ;B[fm]BL[850];W[fe]WL[830];B[dh]BL[846];W[pg]WL[813];B[qp]BL[842];W[qq]WL[806];B[rq]BL[839];W[qo]WL[806] 8 | ;B[rp]BL[835];W[po]WL[806];B[ro]BL[832];W[qr]WL[805];B[pn]BL[828];W[qk]WL[788];B[mp]BL[823];W[mq]WL[778] 9 | ;B[lp]BL[820];W[rm]WL[773];B[rn]BL[816];W[lq]WL[772];B[pq]BL[812];W[qg]WL[766];B[pf]BL[808];W[og]WL[764] 10 | ;B[pr]BL[804];W[or]WL[758];B[op]BL[800];W[oo]WL[752];B[pj]BL[796];W[qj]WL[745];B[qi]BL[793];W[ri]WL[739] 11 | ;B[no]BL[789];W[on]WL[733];B[om]BL[785];W[nn]WL[727];B[rh]BL[782];W[pi]WL[721];B[qh]BL[777];W[rg]WL[716] 12 | ;B[ph]BL[773];W[oi]WL[710];B[mn]BL[770];W[nm]WL[704];B[nl]BL[766];W[mm]WL[702];B[oh]BL[762];W[nh]WL[695] 13 | ;B[ni]BL[758];W[sh]WL[689];B[lm]BL[754];W[ml]WL[687]) 14 | 15 | -------------------------------------------------------------------------------- /ladder_suite/ladder/409252.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[qin_ehh]PB[Zen-15.7p-1c1g]WR[3752]BR[3526]DT[2018-04-07]PC[(CGOS) 19x19 Computer Go Server]RE[B+Resign]GN[409252] 4 | ;B[qd]BL[895];W[pp]WL[896];B[dc]BL[890];W[dp]WL[892];B[cn]BL[885];W[de]WL[889];B[fq]BL[879];W[fp]WL[885] 5 | ;B[gp]BL[878];W[fo]WL[881];B[dq]BL[877];W[gq]WL[878];B[eq]BL[872];W[hp]WL[874];B[go]BL[868];W[hq]WL[869] 6 | ;B[cp]BL[862];W[do]WL[865];B[co]BL[858];W[gn]WL[862];B[ho]BL[854];W[cq]WL[858];B[fn]BL[849];W[en]WL[854] 7 | ;B[fm]BL[844];W[em]WL[850];B[eo]BL[839];W[ep]WL[847];B[dn]BL[834];W[eo]WL[843];B[el]BL[829]) 8 | 9 | -------------------------------------------------------------------------------- /ladder_suite/ladder/409279.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[han_gaf]PB[Pangu-127-n2]WR[3780?]BR[3710?]DT[2018-04-07]PC[(CGOS) 19x19 Computer Go Server]RE[B+Resign]GN[409279] 4 | ;B[dp]BL[898];W[pd]WL[896];B[cd]BL[882];W[pp]WL[892];B[nc]BL[878];W[ed]WL[889];B[qf]BL[866];W[pf]WL[885] 5 | ;B[pg]BL[865];W[of]WL[881];B[qd]BL[865];W[qg]WL[878];B[qe]BL[858];W[ph]WL[874];B[og]BL[852];W[qh]WL[869] 6 | ;B[pc]BL[850];W[ng]WL[866];B[oh]BL[844];W[od]WL[862];B[oc]BL[838];W[oi]WL[858];B[nh]BL[832];W[mh]WL[854] 7 | ;B[ni]BL[826];W[nj]WL[851];B[mi]BL[820];W[li]WL[847];B[mj]BL[815];W[mk]WL[844];B[lj]BL[811];W[kj]WL[841] 8 | ;B[lk]BL[806];W[ll]WL[837];B[kk]BL[803];W[jk]WL[834];B[kl]BL[802]) 9 | 10 | -------------------------------------------------------------------------------- /ladder_suite/ladder/409355.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[han_gaf]PB[Pangu-127-n2]WR[3810?]BR[3659?]DT[2018-04-08]PC[(CGOS) 19x19 Computer Go Server]RE[B+Resign]GN[409355] 4 | ;B[pd]BL[898];W[pp]WL[896];B[dc]BL[886];W[dp]WL[892];B[cn]BL[881];W[de]WL[888];B[ce]BL[864];W[cf]WL[885] 5 | ;B[cd]BL[863];W[df]WL[881];B[fq]BL[855];W[dn]WL[877];B[dm]BL[849];W[en]WL[873];B[cp]BL[848];W[cm]WL[870] 6 | ;B[co]BL[841];W[dl]WL[866];B[em]BL[836];W[cl]WL[861];B[dq]BL[835];W[fp]WL[858];B[ep]BL[828];W[ec]WL[854] 7 | ;B[eb]BL[828];W[fm]WL[850];B[el]BL[821];W[dd]WL[846];B[cb]BL[813];W[ek]WL[842];B[fl]BL[808];W[bc]WL[838] 8 | ;B[cc]BL[801];W[eo]WL[835];B[do]BL[795];W[gl]WL[831];B[fk]BL[789];W[fj]WL[827];B[gk]BL[784]) 9 | 10 | -------------------------------------------------------------------------------- /ladder_suite/ladder/409377.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[han_gaf]PB[Pangu-127-n]WR[3795?]BR[3688]DT[2018-04-08]PC[(CGOS) 19x19 Computer Go Server]RE[B+Resign]GN[409377] 4 | ;B[pp]BL[899];W[dp]WL[896];B[qd]BL[884];W[dd]WL[892];B[fc]BL[880];W[od]WL[888];B[cf]BL[867];W[fd]WL[884] 5 | ;B[gd]BL[862];W[fe]WL[881];B[dc]BL[857];W[gc]WL[877];B[ec]BL[850];W[hd]WL[873];B[ge]BL[844];W[hc]WL[869] 6 | ;B[cd]BL[842];W[ce]WL[865];B[de]BL[836];W[gf]WL[861];B[he]BL[829];W[df]WL[857];B[be]BL[823];W[ie]WL[853] 7 | ;B[hf]BL[818];W[hg]WL[850];B[if]BL[812];W[jf]WL[846];B[ig]BL[806]) 8 | 9 | -------------------------------------------------------------------------------- /ladder_suite/ladder/409399.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[qin_ehh]PB[Pangu-127-n2]WR[3736]BR[3680?]DT[2018-04-08]PC[(CGOS) 19x19 Computer Go Server]RE[B+Resign]GN[409399] 4 | ;B[pp]BL[898];W[dp]WL[896];B[qd]BL[882];W[dd]WL[892];B[fc]BL[877];W[od]WL[888];B[cf]BL[863];W[fd]WL[884] 5 | ;B[gd]BL[859];W[fe]WL[881];B[dc]BL[856];W[cd]WL[877];B[cc]BL[847];W[gc]WL[873];B[ec]BL[841];W[hd]WL[869] 6 | ;B[ge]BL[836];W[hc]WL[865];B[ed]BL[835];W[ee]WL[861];B[de]BL[829];W[gf]WL[858];B[he]BL[823];W[ie]WL[854] 7 | ;B[hf]BL[817];W[hg]WL[850];B[if]BL[811];W[ce]WL[847];B[df]BL[805];W[jf]WL[843];B[ig]BL[800];W[ih]WL[839] 8 | ;B[jg]BL[795]) 9 | 10 | -------------------------------------------------------------------------------- /ladder_suite/ladder/409445.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[Pangu-139-n]PB[qin_ehh]WR[3026?]BR[3732]DT[2018-04-08]PC[(CGOS) 19x19 Computer Go Server]RE[W+Resign]GN[409445] 4 | ;B[dd]BL[896];W[pp]WL[898];B[dp]BL[892];W[pd]WL[891];B[nc]BL[889];W[qf]WL[884];B[pc]BL[885];W[qc]WL[878] 5 | ;B[qb]BL[881];W[oc]WL[877];B[pb]BL[877];W[od]WL[877];B[ob]BL[873];W[cq]WL[873];B[dq]BL[870];W[cp]WL[866] 6 | ;B[cn]BL[866];W[co]WL[866];B[do]BL[863];W[bn]WL[866];B[cr]BL[859];W[br]WL[858];B[bm]BL[855];W[dn]WL[855] 7 | ;B[cm]BL[851];W[dr]WL[854];B[er]BL[847];W[cs]WL[854];B[en]BL[844];W[dm]WL[847];B[dl]BL[839];W[em]WL[841] 8 | ;B[fm]BL[836];W[el]WL[834];B[ek]BL[832];W[fl]WL[830];B[gl]BL[829];W[fk]WL[826];B[fj]BL[825];W[gk]WL[826] 9 | ;B[hk]BL[822];W[gj]WL[825];B[gi]BL[819];W[hj]WL[825];B[ij]BL[815];W[hi]WL[825];B[hh]BL[812];W[ii]WL[825] 10 | ;B[ji]BL[809];W[ih]WL[823];B[ig]BL[805];W[jh]WL[823];B[kh]BL[802];W[jg]WL[823];B[jf]BL[798];W[kg]WL[822] 11 | ;B[lg]BL[795];W[kf]WL[821];B[ke]BL[792];W[lf]WL[820];B[mf]BL[788];W[le]WL[820];B[ld]BL[785];W[me]WL[819] 12 | ;B[ne]BL[781];W[md]WL[819];B[nd]BL[778];W[mc]WL[818];B[mb]BL[774];W[lc]WL[817];B[lb]BL[756];W[kd]WL[813] 13 | ) 14 | 15 | -------------------------------------------------------------------------------- /ladder_suite/ladder/409477.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[qin_ehh]PB[Pangu-139-n]WR[3733]BR[3415?]DT[2018-04-08]PC[(CGOS) 19x19 Computer Go Server]RE[B+Resign]GN[409477] 4 | ;B[pp]BL[898];W[dd]WL[896];B[qd]BL[882];W[dp]WL[892];B[fc]BL[876];W[od]WL[888];B[oc]BL[864];W[nc]WL[885] 5 | ;B[pc]BL[864];W[nd]WL[881];B[cf]BL[848];W[fd]WL[877];B[gd]BL[842];W[fe]WL[873];B[dc]BL[841];W[gc]WL[870] 6 | ;B[ec]BL[835];W[hd]WL[866];B[ge]BL[830];W[hc]WL[862];B[cd]BL[829];W[gf]WL[858];B[he]BL[823];W[ie]WL[854] 7 | ;B[hf]BL[817];W[ce]WL[850];B[de]BL[811];W[hg]WL[846];B[if]BL[805];W[df]WL[843];B[be]BL[799];W[jf]WL[839] 8 | ;B[ig]BL[794];W[ih]WL[835];B[jg]BL[789];W[kg]WL[832];B[jh]BL[785];W[ji]WL[828];B[kh]BL[782]) 9 | 10 | -------------------------------------------------------------------------------- /ladder_suite/ladder/409563.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[Pangu-127-n2]PB[qin_ehh]WR[3692?]BR[3732]DT[2018-04-08]PC[(CGOS) 19x19 Computer Go Server]RE[W+Resign]GN[409563] 4 | ;B[pd]BL[896];W[dp]WL[898];B[pp]BL[892];W[dd]WL[891];B[fc]BL[889];W[cf]WL[884];B[dc]BL[885];W[cc]WL[877] 5 | ;B[cb]BL[881];W[ec]WL[877];B[db]BL[877];W[ed]WL[877];B[eb]BL[873];W[qq]WL[871];B[pq]BL[869];W[qp]WL[865] 6 | ;B[qn]BL[866];W[qo]WL[864];B[po]BL[862];W[rn]WL[864];B[qr]BL[859];W[rr]WL[862];B[rm]BL[855];W[pn]WL[862] 7 | ;B[qm]BL[850];W[pr]WL[861];B[or]BL[847];W[qs]WL[861];B[on]BL[844];W[pm]WL[854];B[pl]BL[839];W[om]WL[847] 8 | ;B[nm]BL[835];W[ol]WL[841];B[ok]BL[832];W[nl]WL[836];B[ml]BL[828];W[nk]WL[830];B[nj]BL[825];W[mk]WL[828] 9 | ;B[lk]BL[822];W[mj]WL[826];B[mi]BL[818];W[lj]WL[826];B[kj]BL[815];W[li]WL[826];B[lh]BL[811];W[ki]WL[825] 10 | ;B[ji]BL[808];W[kh]WL[825];B[kg]BL[805];W[jh]WL[824];B[ih]BL[801];W[jg]WL[824];B[jf]BL[798];W[ig]WL[824] 11 | ;B[hg]BL[795];W[if]WL[823];B[ie]BL[791];W[hf]WL[823];B[gf]BL[788];W[he]WL[822];B[hd]BL[785];W[ge]WL[822] 12 | ;B[fe]BL[781];W[gd]WL[822];B[fd]BL[778];W[gc]WL[821];B[gb]BL[774];W[hc]WL[821];B[ee]BL[767];W[gg]WL[805] 13 | ;B[ic]BL[760];W[ff]WL[783]) 14 | 15 | -------------------------------------------------------------------------------- /ladder_suite/ladder/409598.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[han_gaf]PB[Zen-15.7-1c0g]WR[3840?]BR[3227]DT[2018-04-08]PC[(CGOS) 19x19 Computer Go Server]RE[B+Resign]GN[409598] 4 | ;B[pd]BL[895];W[pp]WL[896];B[dc]BL[890];W[dp]WL[892];B[cn]BL[885];W[de]WL[888];B[fq]BL[880];W[fp]WL[884] 5 | ;B[gp]BL[879];W[fo]WL[881];B[dq]BL[878];W[gq]WL[877];B[eq]BL[873];W[hp]WL[873];B[go]BL[868];W[hq]WL[869] 6 | ;B[cp]BL[860];W[co]WL[865];B[do]BL[855];W[gn]WL[861];B[ho]BL[850];W[dn]WL[857];B[bo]BL[845];W[io]WL[853] 7 | ;B[hn]BL[843];W[hm]WL[850];B[in]BL[837];W[jn]WL[846];B[im]BL[833]) 8 | 9 | -------------------------------------------------------------------------------- /ladder_suite/ladder/409600.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[qin_ehh]PB[Pangu-127-n2]WR[3729]BR[3705?]DT[2018-04-08]PC[(CGOS) 19x19 Computer Go Server]RE[B+Resign]GN[409600] 4 | ;B[pp]BL[899];W[dd]WL[896];B[qd]BL[882];W[dp]WL[892];B[fc]BL[877];W[od]WL[888];B[oc]BL[862];W[nc]WL[884] 5 | ;B[pc]BL[861];W[nd]WL[881];B[cf]BL[851];W[fd]WL[877];B[gd]BL[845];W[fe]WL[873];B[dc]BL[845];W[gc]WL[869] 6 | ;B[ec]BL[838];W[hd]WL[865];B[ge]BL[832];W[hc]WL[862];B[cd]BL[832];W[df]WL[857];B[de]BL[825];W[gf]WL[853] 7 | ;B[he]BL[819];W[ee]WL[850];B[ed]BL[813];W[ie]WL[846];B[hf]BL[807];W[ce]WL[843];B[be]BL[801];W[hg]WL[838] 8 | ;B[if]BL[795];W[jf]WL[835];B[ig]BL[789];W[ih]WL[829];B[jg]BL[784];W[kg]WL[826];B[jh]BL[780];W[ji]WL[822] 9 | ;B[kh]BL[777]) 10 | 11 | -------------------------------------------------------------------------------- /ladder_suite/ladder/409608.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[Pangu-139-n]PB[han_gaf]WR[3707?]BR[3819?]DT[2018-04-08]PC[(CGOS) 19x19 Computer Go Server]RE[W+Resign]GN[409608] 4 | ;B[pp]BL[895];W[dd]WL[898];B[dp]BL[892];W[pd]WL[890];B[cf]BL[888];W[fc]WL[885];B[qf]BL[884];W[nc]WL[876] 5 | ;B[cn]BL[880];W[qq]WL[870];B[qp]BL[876];W[pq]WL[865];B[nq]BL[873];W[oq]WL[862];B[op]BL[869];W[nr]WL[861] 6 | ;B[rq]BL[866];W[rr]WL[861];B[or]BL[863];W[os]WL[847];B[mr]BL[857];W[pr]WL[846];B[mq]BL[854];W[qi]WL[838] 7 | ;B[pl]BL[850];W[ok]WL[831];B[qd]BL[846];W[qc]WL[825];B[rc]BL[843];W[qe]WL[825];B[rd]BL[839];W[pe]WL[824] 8 | ;B[re]BL[835];W[qb]WL[820];B[pf]BL[832];W[rg]WL[819];B[rf]BL[828];W[oi]WL[819];B[ph]BL[823];W[ol]WL[813] 9 | ;B[md]BL[819];W[mc]WL[806];B[ld]BL[816];W[lc]WL[804];B[jd]BL[812];W[pm]WL[795];B[cd]BL[808];W[cc]WL[789] 10 | ;B[bc]BL[805];W[ce]WL[788];B[bd]BL[801];W[de]WL[787];B[be]BL[796];W[jp]WL[784];B[kc]BL[793];W[ke]WL[768] 11 | ;B[kd]BL[789];W[np]WL[766];B[pn]BL[785];W[no]WL[765];B[nn]BL[781];W[mn]WL[761];B[om]BL[778];W[qm]WL[761] 12 | ;B[mm]BL[774];W[oo]WL[760];B[on]BL[771];W[lo]WL[760];B[ql]BL[766];W[qn]WL[754];B[po]BL[762];W[rl]WL[754] 13 | ;B[mo]BL[759];W[mp]WL[753];B[lp]BL[755];W[mo]WL[753];B[ko]BL[752];W[ln]WL[753];B[pj]BL[748];W[pi]WL[744] 14 | ;B[rk]BL[745];W[qk]WL[737];B[pk]BL[739];W[oj]WL[726];B[lm]BL[735];W[kn]WL[718];B[jn]BL[731];W[km]WL[716] 15 | ;B[kl]BL[727];W[jm]WL[716];B[qj]BL[724];W[rj]WL[715];B[im]BL[719];W[jl]WL[715];B[jk]BL[716];W[il]WL[714] 16 | ;B[ri]BL[712];W[qk]WL[705];B[hl]BL[708];W[ik]WL[704];B[ij]BL[705];W[hk]WL[701];B[gk]BL[701];W[hj]WL[701] 17 | ;B[hi]BL[698];W[gj]WL[700];B[fj]BL[694];W[gi]WL[699];B[gh]BL[691];W[fi]WL[699];B[ei]BL[688];W[fh]WL[699] 18 | ;B[fg]BL[684];W[eh]WL[697];B[dh]BL[681];W[eg]WL[696];B[ef]BL[677];W[dg]WL[695];B[df]BL[674];W[cg]WL[695] 19 | ) 20 | 21 | -------------------------------------------------------------------------------- /ladder_suite/ladder/409643.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[Pangu-139-n]PB[qin_ehh]WR[3752?]BR[3727]DT[2018-04-08]PC[(CGOS) 19x19 Computer Go Server]RE[W+Resign]GN[409643] 4 | ;B[pd]BL[896];W[dp]WL[898];B[dd]BL[892];W[pp]WL[891];B[cn]BL[888];W[fq]WL[885];B[cp]BL[884];W[cq]WL[878] 5 | ;B[bq]BL[881];W[co]WL[878];B[bp]BL[877];W[do]WL[878];B[bo]BL[873];W[qc]WL[873];B[qd]BL[869];W[pc]WL[867] 6 | ;B[nc]BL[865];W[oc]WL[866];B[od]BL[862];W[nb]WL[866];B[rc]BL[859];W[rb]WL[860];B[mb]BL[854];W[nd]WL[858] 7 | ;B[mc]BL[850];W[rd]WL[858];B[re]BL[847];W[sc]WL[857];B[ne]BL[843];W[md]WL[850];B[ld]BL[838];W[me]WL[843] 8 | ;B[mf]BL[835];W[le]WL[837];B[ke]BL[831];W[lf]WL[832];B[lg]BL[828];W[kf]WL[828];B[jf]BL[824];W[kg]WL[828] 9 | ;B[kh]BL[821];W[jg]WL[828];B[ig]BL[818];W[jh]WL[828];B[ji]BL[814];W[ih]WL[827];B[hh]BL[811];W[ii]WL[827] 10 | ;B[ij]BL[808];W[hi]WL[826];B[gi]BL[804];W[hj]WL[826];B[hk]BL[801];W[gj]WL[825];B[fj]BL[798];W[gk]WL[825] 11 | ;B[gl]BL[794];W[fk]WL[824];B[ek]BL[791];W[fl]WL[824];B[fm]BL[787];W[el]WL[823];B[dl]BL[784];W[em]WL[822] 12 | ;B[en]BL[781];W[dm]WL[822];B[dn]BL[777];W[cm]WL[821];B[bm]BL[773];W[cl]WL[820]) 13 | 14 | -------------------------------------------------------------------------------- /ladder_suite/ladder/409806.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[feliks]PB[han_gaf]WR[2860?]BR[3803?]DT[2018-04-08]PC[(CGOS) 19x19 Computer Go Server]RE[W+Resign]GN[409806] 4 | ;B[dd]BL[896];W[pp]WL[900];B[dq]BL[892];W[pd]WL[900];B[do]BL[888];W[jq]WL[900];B[fc]BL[884];W[qn]WL[887] 5 | ;B[nc]BL[880];W[pf]WL[875];B[oe]BL[876];W[pe]WL[873];B[pb]BL[872];W[qc]WL[861];B[ld]BL[867];W[ci]WL[849] 6 | ;B[ck]BL[863];W[cf]WL[838];B[ce]BL[860];W[df]WL[835];B[di]BL[856];W[dh]WL[833];B[dj]BL[852];W[ed]WL[822] 7 | ;B[ec]BL[847];W[cc]WL[818];B[cd]BL[844];W[dc]WL[807];B[ee]BL[839];W[fd]WL[805];B[gd]BL[835];W[fe]WL[803] 8 | ;B[bc]BL[831];W[bb]WL[801];B[ff]BL[828];W[ge]WL[798];B[eb]BL[824];W[bd]WL[787];B[cb]BL[820];W[ac]WL[785] 9 | ;B[he]BL[815];W[gf]WL[783];B[gg]BL[812];W[hf]WL[781]) 10 | 11 | -------------------------------------------------------------------------------- /ladder_suite/ladder/409826.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[Zen-15.7-1c0g]PB[han_gaf]WR[3229]BR[3799?]DT[2018-04-08]PC[(CGOS) 19x19 Computer Go Server]RE[W+Resign]GN[409826] 4 | ;B[dp]BL[896];W[pp]WL[895];B[cd]BL[892];W[pc]WL[893];B[ed]BL[888];W[cn]WL[885];B[qe]BL[884];W[fq]WL[880] 5 | ;B[dn]BL[880];W[dm]WL[877];B[en]BL[877];W[cp]WL[876];B[cm]BL[873];W[co]WL[871];B[dl]BL[869];W[em]WL[866] 6 | ;B[cl]BL[864];W[do]WL[856];B[fm]BL[860];W[el]WL[851];B[eo]BL[855];W[ep]WL[848];B[ek]BL[851];W[fl]WL[843] 7 | ;B[gl]BL[847];W[fk]WL[837];B[fj]BL[844];W[gk]WL[833];B[hk]BL[840];W[gj]WL[828];B[gi]BL[836];W[hj]WL[827] 8 | ;B[ij]BL[832];W[hi]WL[821];B[hh]BL[828];W[ii]WL[819];B[ji]BL[824];W[ih]WL[815];B[ig]BL[821];W[jh]WL[811] 9 | ;B[kh]BL[816];W[jg]WL[808];B[jf]BL[812];W[kg]WL[806];B[lg]BL[808];W[kf]WL[803];B[ke]BL[804];W[lf]WL[800] 10 | ;B[mf]BL[800];W[le]WL[798];B[ld]BL[796];W[me]WL[795];B[ne]BL[792];W[md]WL[793]) 11 | 12 | -------------------------------------------------------------------------------- /ladder_suite/ladder/409848.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[washington]PB[Zen-15.9-1c1g]WR[2947?]BR[3608]DT[2018-04-08]PC[(CGOS) 19x19 Computer Go Server]RE[B+Resign]GN[409848] 4 | ;B[pd]BL[894];W[dd]WL[889];B[qp]BL[890];W[dp]WL[886];B[fq]BL[885];W[op]WL[882];B[cn]BL[880];W[fp]WL[878] 5 | ;B[gp]BL[876];W[fo]WL[875];B[dq]BL[875];W[gq]WL[871];B[eq]BL[870];W[hp]WL[867];B[go]BL[866];W[hq]WL[862] 6 | ;B[cp]BL[862];W[gn]WL[857];B[ho]BL[858];W[do]WL[854];B[co]BL[854];W[cq]WL[850];B[fn]BL[849];W[en]WL[846] 7 | ;B[fm]BL[844];W[io]WL[842];B[hn]BL[843];W[em]WL[839];B[eo]BL[838];W[ep]WL[834];B[dn]BL[832];W[eo]WL[831] 8 | ;B[el]BL[827];W[dm]WL[827];B[dl]BL[822]) 9 | 10 | -------------------------------------------------------------------------------- /ladder_suite/ladder/409856.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[han_gaf]PB[Pangu-127-n2]WR[3781?]BR[3710]DT[2018-04-08]PC[(CGOS) 19x19 Computer Go Server]RE[B+Resign]GN[409856] 4 | ;B[dp]BL[898];W[dd]WL[896];B[pq]BL[882];W[pd]WL[892];B[qf]BL[878];W[po]WL[888];B[nc]BL[868];W[pf]WL[884] 5 | ;B[pg]BL[863];W[of]WL[881];B[qd]BL[859];W[qg]WL[877];B[qe]BL[852];W[ph]WL[874];B[og]BL[847];W[qh]WL[869] 6 | ;B[pc]BL[845];W[oc]WL[865];B[od]BL[838];W[ng]WL[861];B[oh]BL[832];W[oi]WL[857];B[nh]BL[827];W[nd]WL[853] 7 | ;B[ob]BL[821];W[mi]WL[849];B[ni]BL[807]) 8 | 9 | -------------------------------------------------------------------------------- /ladder_suite/ladder/409867.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[han_gaf]PB[Zen-15.7-1c0g]WR[3771?]BR[3231]DT[2018-04-08]PC[(CGOS) 19x19 Computer Go Server]RE[B+Resign]GN[409867] 4 | ;B[pd]BL[895];W[pp]WL[896];B[dc]BL[890];W[dp]WL[892];B[cn]BL[882];W[de]WL[888];B[fq]BL[877];W[fp]WL[884] 5 | ;B[gp]BL[876];W[fo]WL[881];B[dq]BL[874];W[gq]WL[877];B[eq]BL[869];W[hp]WL[873];B[go]BL[864];W[hq]WL[869] 6 | ;B[cp]BL[860];W[dn]WL[865];B[do]BL[853];W[gn]WL[861];B[ho]BL[849];W[io]WL[857];B[hn]BL[845];W[hm]WL[854] 7 | ;B[in]BL[840];W[eo]WL[850];B[ep]BL[835];W[jn]WL[846];B[im]BL[830];W[il]WL[842];B[jm]BL[825];W[km]WL[839] 8 | ;B[jl]BL[823];W[jk]WL[836];B[kl]BL[818]) 9 | 10 | -------------------------------------------------------------------------------- /ladder_suite/ladder/409993.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[han_gaf]PB[Pangu-139-n]WR[3771]BR[3787?]DT[2018-04-09]PC[(CGOS) 19x19 Computer Go Server]RE[B+Resign]GN[409993] 4 | ;B[dp]BL[898];W[pp]WL[896];B[cd]BL[886];W[pd]WL[892];B[nc]BL[882];W[ed]WL[888];B[ec]BL[869];W[fc]WL[885] 5 | ;B[dc]BL[867];W[fd]WL[881];B[qf]BL[863];W[nd]WL[877];B[md]BL[857];W[ne]WL[873];B[pc]BL[857];W[mc]WL[869] 6 | ;B[oc]BL[851];W[ld]WL[866];B[me]BL[846];W[lc]WL[861];B[qd]BL[845];W[pf]WL[857];B[pe]BL[838];W[ce]WL[853] 7 | ;B[be]BL[832];W[bf]WL[849];B[de]BL[831];W[cf]WL[845];B[dd]BL[830];W[mf]WL[842];B[le]BL[824];W[ke]WL[838] 8 | ;B[lf]BL[818];W[bd]WL[834];B[bc]BL[812];W[lg]WL[830];B[kf]BL[806];W[oe]WL[826];B[od]BL[800];W[jf]WL[822] 9 | ;B[kg]BL[795];W[kh]WL[819];B[jg]BL[789]) 10 | 11 | -------------------------------------------------------------------------------- /ladder_suite/ladder/410034.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[han_gaf]PB[Pangu-139-n]WR[3770]BR[3799?]DT[2018-04-09]PC[(CGOS) 19x19 Computer Go Server]RE[B+Resign]GN[410034] 4 | ;B[pd]BL[898];W[dd]WL[896];B[qp]BL[887];W[dp]WL[892];B[fq]BL[884];W[op]WL[887];B[oq]BL[870];W[nq]WL[883] 5 | ;B[pq]BL[869];W[np]WL[879];B[cn]BL[862];W[fp]WL[874];B[gp]BL[856];W[fo]WL[870];B[dq]BL[856];W[gq]WL[866] 6 | ;B[eq]BL[849];W[hp]WL[860];B[go]BL[843];W[hq]WL[855];B[cp]BL[842];W[dn]WL[852];B[do]BL[836];W[qo]WL[847] 7 | ;B[ro]BL[828];W[rn]WL[843];B[po]BL[827];W[qn]WL[839];B[pp]BL[826];W[gn]WL[836];B[ho]BL[820];W[rp]WL[831] 8 | ;B[rq]BL[814];W[io]WL[827];B[hn]BL[807];W[hm]WL[824];B[in]BL[801];W[eo]WL[820];B[ep]BL[795];W[jn]WL[816] 9 | ;B[im]BL[790];W[il]WL[813];B[jm]BL[785];W[km]WL[809];B[jl]BL[780]) 10 | 11 | -------------------------------------------------------------------------------- /ladder_suite/ladder/410217.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[washington]PB[Zen-15.7-1c0g]WR[3688?]BR[3231]DT[2018-04-09]PC[(CGOS) 19x19 Computer Go Server]RE[B+Resign]GN[410217] 4 | ;B[pd]BL[895];W[dd]WL[896];B[qp]BL[893];W[dp]WL[892];B[fq]BL[889];W[op]WL[888];B[cn]BL[884];W[dn]WL[884] 5 | ;B[dm]BL[882];W[en]WL[881];B[cp]BL[881];W[cm]WL[877];B[co]BL[876];W[dl]WL[874];B[em]BL[871];W[cl]WL[869] 6 | ;B[dq]BL[862];W[fm]WL[865];B[el]BL[857];W[ep]WL[861];B[eq]BL[853];W[cq]WL[857];B[bq]BL[847];W[ej]WL[853] 7 | ;B[ek]BL[842];W[dj]WL[849];B[gl]BL[837];W[gp]WL[846];B[fp]BL[828];W[hn]WL[841];B[gj]BL[823];W[qo]WL[838] 8 | ;B[ro]BL[816];W[po]WL[834];B[qn]BL[813];W[rn]WL[830];B[rm]BL[812];W[rp]WL[826];B[sn]BL[810];W[qq]WL[823] 9 | ;B[pn]BL[806];W[fo]WL[818];B[dk]BL[794];W[ck]WL[814];B[cj]BL[788];W[fj]WL[811];B[gk]BL[781];W[ci]WL[806] 10 | ;B[bj]BL[776];W[bk]WL[803];B[bi]BL[771];W[ch]WL[799];B[bh]BL[765];W[bg]WL[795];B[bm]BL[761];W[ak]WL[791] 11 | ;B[al]BL[754];W[aj]WL[787];B[bl]BL[747]) 12 | 13 | -------------------------------------------------------------------------------- /ladder_suite/ladder/410333.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[washington]PB[Pangu-139-n]WR[3766?]BR[3814?]DT[2018-04-09]PC[(CGOS) 19x19 Computer Go Server]RE[B+Resign]GN[410333] 4 | ;B[pd]BL[898];W[dd]WL[896];B[qp]BL[887];W[dp]WL[892];B[fq]BL[883];W[op]WL[888];B[oq]BL[870];W[nq]WL[885] 5 | ;B[pq]BL[870];W[np]WL[881];B[cn]BL[861];W[fp]WL[878];B[gp]BL[855];W[fo]WL[874];B[dq]BL[854];W[gq]WL[869] 6 | ;B[eq]BL[847];W[hp]WL[866];B[go]BL[842];W[hq]WL[861];B[cp]BL[841];W[dn]WL[857];B[do]BL[835];W[gn]WL[853] 7 | ;B[ho]BL[828];W[eo]WL[850];B[ep]BL[822];W[io]WL[846];B[hn]BL[816];W[hm]WL[842];B[in]BL[811];W[jn]WL[839] 8 | ;B[im]BL[806];W[il]WL[835];B[jm]BL[800]) 9 | 10 | -------------------------------------------------------------------------------- /ladder_suite/ladder/410605.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[Zen-15.7p-1c1g]PB[adams]WR[3523]BR[3270?]DT[2018-04-10]PC[(CGOS) 19x19 Computer Go Server]RE[W+Resign]GN[410605] 4 | ;B[dp]BL[896];W[pp]WL[895];B[cd]BL[892];W[pc]WL[894];B[fd]BL[888];W[cn]WL[886];B[qe]BL[885];W[fq]WL[881] 5 | ;B[dn]BL[881];W[dm]WL[877];B[en]BL[877];W[cp]WL[876];B[cm]BL[873];W[co]WL[872];B[dl]BL[870];W[em]WL[867] 6 | ;B[cl]BL[865];W[fm]WL[865];B[fp]BL[862];W[gp]WL[860];B[dq]BL[858];W[fo]WL[853];B[ep]BL[854];W[cq]WL[852] 7 | ;B[cr]BL[851];W[br]WL[851];B[gq]BL[847];W[hq]WL[843];B[gr]BL[842];W[hp]WL[842];B[hr]BL[839];W[ir]WL[841] 8 | ;B[fn]BL[835];W[gn]WL[835];B[er]BL[831];W[cs]WL[832];B[gm]BL[827];W[ek]WL[831];B[hn]BL[824];W[go]WL[828] 9 | ;B[hm]BL[820];W[dr]WL[821];B[eo]BL[815];W[jq]WL[816];B[ip]BL[811];W[iq]WL[809];B[el]BL[807];W[fl]WL[804] 10 | ;B[fk]BL[804];W[gl]WL[803];B[gk]BL[800];W[hl]WL[796];B[il]BL[796];W[hk]WL[789];B[hj]BL[793];W[ik]WL[782] 11 | ) 12 | 13 | -------------------------------------------------------------------------------- /ladder_suite/ladder/410615.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[adams]PB[Zen-15.7p-1c1g]WR[3241?]BR[3524]DT[2018-04-10]PC[(CGOS) 19x19 Computer Go Server]RE[B+Resign]GN[410615] 4 | ;B[qd]BL[895];W[dd]WL[895];B[pq]BL[891];W[dp]WL[891];B[fc]BL[890];W[od]WL[887];B[cf]BL[886];W[fd]WL[883] 5 | ;B[gd]BL[882];W[fe]WL[880];B[dc]BL[881];W[gc]WL[876];B[ec]BL[876];W[hd]WL[872];B[cd]BL[875];W[qc]WL[869] 6 | ;B[rc]BL[868];W[pc]WL[864];B[qg]BL[867];W[qo]WL[860];B[pk]BL[858];W[op]WL[856];B[ge]BL[853];W[qf]WL[852] 7 | ;B[pf]BL[845];W[pg]WL[848];B[rf]BL[841];W[of]WL[844];B[qe]BL[838];W[oq]WL[841];B[hc]BL[828];W[gb]WL[836] 8 | ;B[hb]BL[822];W[ib]WL[833];B[ic]BL[817];W[id]WL[829];B[jc]BL[811];W[gf]WL[825];B[he]BL[810];W[de]WL[821] 9 | ;B[ce]BL[804];W[ie]WL[817];B[hf]BL[798]) 10 | 11 | -------------------------------------------------------------------------------- /ladder_suite/ladder/410756.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[adams]PB[Zen-15.7-1c0g]WR[3704?]BR[3236]DT[2018-04-10]PC[(CGOS) 19x19 Computer Go Server]RE[B+Resign]GN[410756] 4 | ;B[pd]BL[895];W[dd]WL[896];B[qp]BL[894];W[dp]WL[892];B[fq]BL[888];W[op]WL[888];B[cn]BL[883];W[fp]WL[884] 5 | ;B[gp]BL[879];W[fo]WL[881];B[dq]BL[877];W[gq]WL[877];B[eq]BL[872];W[hp]WL[873];B[go]BL[867];W[hq]WL[869] 6 | ;B[cp]BL[863];W[gn]WL[865];B[ho]BL[859];W[do]WL[861];B[co]BL[856];W[io]WL[857];B[hn]BL[852];W[hm]WL[854] 7 | ;B[in]BL[847];W[jn]WL[850];B[im]BL[842];W[il]WL[847];B[jm]BL[837]) 8 | 9 | -------------------------------------------------------------------------------- /ladder_suite/ladder/410807.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[adams]PB[Zen-15.7-1c0g]WR[3712?]BR[3236]DT[2018-04-10]PC[(CGOS) 19x19 Computer Go Server]RE[B+Resign]GN[410807] 4 | ;B[pd]BL[894];W[dd]WL[896];B[qp]BL[893];W[dp]WL[892];B[fq]BL[889];W[op]WL[888];B[cn]BL[883];W[fp]WL[885] 5 | ;B[gp]BL[879];W[fo]WL[881];B[dq]BL[878];W[gq]WL[877];B[eq]BL[873];W[hp]WL[874];B[go]BL[868];W[hq]WL[869] 6 | ;B[cp]BL[860];W[do]WL[865];B[co]BL[856];W[gn]WL[861];B[ho]BL[853];W[jo]WL[858];B[hn]BL[847];W[hm]WL[854] 7 | ;B[in]BL[837];W[fm]WL[850];B[jn]BL[828];W[il]WL[847];B[ko]BL[818];W[kp]WL[842];B[lp]BL[813];W[lo]WL[839] 8 | ;B[kn]BL[809];W[lq]WL[835];B[mp]BL[806];W[mq]WL[831];B[ip]BL[802];W[jq]WL[827];B[iq]BL[797];W[ir]WL[823] 9 | ;B[jr]BL[796];W[hr]WL[820];B[kr]BL[793];W[kq]WL[816];B[is]BL[790];W[fr]WL[813];B[hs]BL[786]) 10 | 11 | -------------------------------------------------------------------------------- /ladder_suite/ladder/410818.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[kuafu-139]PB[adams]WR[3327?]BR[3631?]DT[2018-04-10]PC[(CGOS) 19x19 Computer Go Server]RE[W+Resign]GN[410818] 4 | ;B[dd]BL[896];W[pp]WL[898];B[dq]BL[892];W[pd]WL[881];B[dn]BL[889];W[cc]WL[861];B[dc]BL[885];W[cd]WL[843] 5 | ;B[cf]BL[881];W[ce]WL[837];B[de]BL[878];W[bf]WL[835];B[cb]BL[875];W[bb]WL[834];B[be]BL[870];W[db]WL[825] 6 | ;B[bc]BL[866];W[ca]WL[824];B[bd]BL[863];W[cb]WL[822];B[bg]BL[860];W[df]WL[820];B[cg]BL[856];W[fc]WL[818] 7 | ;B[ef]BL[850];W[dg]WL[796];B[dh]BL[846];W[eg]WL[780];B[fd]BL[842];W[gd]WL[777];B[ge]BL[838];W[hd]WL[776] 8 | ;B[fg]BL[834];W[eh]WL[761];B[ec]BL[831];W[eb]WL[748];B[ei]BL[826];W[fh]WL[735];B[gh]BL[823];W[fi]WL[722] 9 | ;B[fj]BL[819];W[gi]WL[717];B[hi]BL[815];W[gj]WL[715];B[gk]BL[811];W[hj]WL[712];B[ij]BL[807];W[hk]WL[710] 10 | ;B[hl]BL[803];W[ik]WL[707];B[jk]BL[800];W[il]WL[704];B[im]BL[796];W[jl]WL[701];B[kl]BL[792];W[jm]WL[698] 11 | ;B[jn]BL[788];W[km]WL[695];B[lm]BL[785];W[kn]WL[692];B[ko]BL[781];W[ln]WL[688];B[mn]BL[777];W[lo]WL[684] 12 | ;B[lp]BL[774];W[mo]WL[679]) 13 | 14 | -------------------------------------------------------------------------------- /ladder_suite/ladder/410991.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[adams]PB[Pangu-139-n3]WR[3767?]BR[3534?]DT[2018-04-10]PC[(CGOS) 19x19 Computer Go Server]RE[B+Resign]GN[410991] 4 | ;B[dd]BL[898];W[dp]WL[896];B[pc]BL[886];W[pp]WL[892];B[qn]BL[882];W[pe]WL[888];B[qe]BL[869];W[qf]WL[884] 5 | ;B[qd]BL[869];W[pf]WL[881];B[nq]BL[862];W[pn]WL[877];B[pm]BL[856];W[on]WL[873];B[qp]BL[855];W[qm]WL[868] 6 | ;B[qo]BL[849];W[pl]WL[865];B[om]BL[843];W[ql]WL[860];B[pq]BL[842];W[oc]WL[856];B[ob]BL[842];W[nm]WL[853] 7 | ;B[ol]BL[836];W[op]WL[849];B[oq]BL[829];W[ok]WL[845];B[nl]BL[823];W[pb]WL[841];B[qb]BL[816];W[ml]WL[836] 8 | ;B[nk]BL[810];W[pd]WL[833];B[pa]BL[804];W[nj]WL[829];B[mk]BL[798]) 9 | 10 | -------------------------------------------------------------------------------- /ladder_suite/ladder/411061.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[washington]PB[Pangu-127]WR[3853]BR[3726?]DT[2018-04-10]PC[(CGOS) 19x19 Computer Go Server]RE[B+Resign]GN[411061] 4 | ;B[dd]BL[899];W[pd]WL[895];B[cp]BL[886];W[pp]WL[891];B[nq]BL[880];W[ep]WL[887];B[qn]BL[869];W[np]WL[883] 5 | ;B[mp]BL[867];W[no]WL[879];B[pq]BL[862];W[mq]WL[874];B[oq]BL[857];W[lp]WL[870];B[mo]BL[852];W[lq]WL[865] 6 | ;B[qp]BL[851];W[mn]WL[861];B[lo]BL[846];W[po]WL[856];B[qo]BL[840];W[kn]WL[853];B[ko]BL[835];W[jo]WL[849] 7 | ;B[kp]BL[835];W[kq]WL[846];B[jp]BL[829];W[ip]WL[842];B[jq]BL[825];W[jr]WL[837];B[iq]BL[820]) 8 | 9 | -------------------------------------------------------------------------------- /ladder_suite/ladder/411072.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[adams]PB[nvwa-new]WR[3751?]BR[3606?]DT[2018-04-10]PC[(CGOS) 19x19 Computer Go Server]RE[B+Resign]GN[411072] 4 | ;B[pp]BL[898];W[dp]WL[896];B[pd]BL[879];W[dd]WL[892];B[cc]BL[867];W[dc]WL[888];B[cd]BL[860];W[cf]WL[885] 5 | ;B[ce]BL[859];W[de]WL[881];B[bf]BL[857];W[cb]WL[878];B[bb]BL[855];W[bg]WL[874];B[df]BL[850];W[cg]WL[869] 6 | ;B[db]BL[848];W[ef]WL[866];B[dg]BL[831];W[be]WL[861];B[ca]BL[820];W[dh]WL[857];B[eg]BL[810];W[bd]WL[854] 7 | ;B[bc]BL[809];W[ff]WL[850];B[ei]BL[801];W[di]WL[846];B[fg]BL[800];W[gg]WL[842];B[gf]BL[790];W[ge]WL[838] 8 | ;B[hf]BL[782];W[hg]WL[834];B[he]BL[776];W[fd]WL[830];B[gd]BL[770];W[fe]WL[826];B[ig]BL[769];W[gi]WL[822] 9 | ;B[fi]BL[765];W[hd]WL[819];B[gc]BL[753];W[ej]WL[814];B[fj]BL[743];W[fk]WL[810];B[gj]BL[735];W[fh]WL[807] 10 | ;B[eh]BL[726];W[if]WL[803];B[ie]BL[717];W[id]WL[799];B[je]BL[709]) 11 | 12 | -------------------------------------------------------------------------------- /ladder_suite/ladder/411087.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[washington]PB[kuafu-139]WR[3848]BR[3606?]DT[2018-04-10]PC[(CGOS) 19x19 Computer Go Server]RE[B+Resign]GN[411087] 4 | ;B[pp]BL[898];W[pd]WL[896];B[dc]BL[879];W[dp]WL[892];B[cf]BL[861];W[dd]WL[888];B[ed]BL[841];W[cc]WL[884] 5 | ;B[cd]BL[822];W[de]WL[881];B[ce]BL[815];W[ec]WL[878];B[db]BL[814];W[fd]WL[874];B[ee]BL[813];W[df]WL[871] 6 | ;B[cg]BL[811];W[eb]WL[865];B[ef]BL[794];W[cb]WL[862];B[da]BL[775];W[dg]WL[858];B[dh]BL[761];W[eg]WL[854] 7 | ;B[fg]BL[747];W[eh]WL[851];B[ei]BL[729];W[fh]WL[847];B[gh]BL[710];W[fi]WL[844];B[fj]BL[691];W[gi]WL[841] 8 | ;B[hi]BL[672];W[gj]WL[837];B[gk]BL[654];W[hj]WL[834];B[ij]BL[636];W[hk]WL[830];B[hl]BL[619];W[ik]WL[827] 9 | ;B[jk]BL[602];W[il]WL[823];B[im]BL[584];W[jl]WL[820];B[kl]BL[567];W[jm]WL[817];B[jn]BL[551];W[km]WL[813] 10 | ;B[lm]BL[534];W[kn]WL[810];B[ko]BL[519];W[ln]WL[806];B[mn]BL[504];W[lo]WL[802];B[lp]BL[494];W[mo]WL[799] 11 | ;B[no]BL[483];W[mp]WL[795];B[mq]BL[471];W[np]WL[791];B[nq]BL[460];W[op]WL[781];B[oo]BL[452];W[oq]WL[777] 12 | ;B[or]BL[446];W[pq]WL[774];B[qq]BL[438];W[pr]WL[770];B[qr]BL[431];W[ps]WL[766];B[qs]BL[417]) 13 | 14 | -------------------------------------------------------------------------------- /ladder_suite/ladder/411099.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[adams]PB[ZiGo]WR[3754?]BR[2526?]DT[2018-04-10]PC[(CGOS) 19x19 Computer Go Server]RE[B+Resign]GN[411099] 4 | ;B[dc]BL[894];W[pd]WL[896];B[pp]BL[888];W[dp]WL[892];B[qc]BL[884];W[qd]WL[888];B[pc]BL[878];W[nc]WL[885] 5 | ;B[oc]BL[873];W[od]WL[881];B[nb]BL[870];W[ce]WL[878];B[fd]BL[865];W[rc]WL[873];B[rb]BL[861];W[mb]WL[869] 6 | ;B[nd]BL[853];W[mc]WL[866];B[rd]BL[847];W[re]WL[862];B[sc]BL[842];W[ne]WL[858];B[cq]BL[836];W[dq]WL[854] 7 | ;B[cp]BL[829];W[co]WL[850];B[bo]BL[823];W[bn]WL[846];B[cn]BL[817];W[do]WL[843];B[bm]BL[811];W[bp]WL[840] 8 | ;B[an]BL[807];W[bq]WL[836];B[qn]BL[801];W[kq]WL[830];B[mq]BL[796];W[ch]WL[826];B[cj]BL[789];W[cc]WL[823] 9 | ;B[cb]BL[782];W[bd]WL[819];B[ic]BL[775];W[ko]WL[815];B[md]BL[768];W[ld]WL[811];B[me]BL[762];W[mf]WL[807] 10 | ;B[le]BL[750];W[ke]WL[803];B[lf]BL[742];W[lg]WL[799];B[kf]BL[737]) 11 | 12 | -------------------------------------------------------------------------------- /ladder_suite/ladder/411106.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[nvwa-new]PB[adams]WR[3629?]BR[3727?]DT[2018-04-10]PC[(CGOS) 19x19 Computer Go Server]RE[W+Resign]GN[411106] 4 | ;B[pd]BL[896];W[pp]WL[898];B[cd]BL[892];W[dp]WL[888];B[fd]BL[888];W[qc]WL[875];B[qd]BL[884];W[pc]WL[862] 5 | ;B[nc]BL[881];W[oc]WL[861];B[od]BL[877];W[nb]WL[860];B[rc]BL[874];W[rb]WL[858];B[ob]BL[870];W[rd]WL[853] 6 | ;B[qb]BL[866];W[sc]WL[851];B[pb]BL[863];W[rc]WL[850];B[mb]BL[859];W[nd]WL[848];B[mc]BL[856];W[qf]WL[846] 7 | ;B[ne]BL[850];W[md]WL[830];B[pf]BL[846];W[pg]WL[818];B[ld]BL[842];W[me]WL[809];B[og]BL[838];W[ph]WL[808] 8 | ;B[mf]BL[834];W[le]WL[799];B[qe]BL[831];W[re]WL[790];B[ke]BL[827];W[lf]WL[781];B[lg]BL[823];W[kf]WL[774] 9 | ;B[jf]BL[819];W[kg]WL[773];B[kh]BL[816];W[jg]WL[771];B[ig]BL[812];W[jh]WL[770];B[ji]BL[808];W[ih]WL[768] 10 | ;B[hh]BL[804];W[ii]WL[766];B[ij]BL[800];W[hi]WL[764];B[gi]BL[796];W[hj]WL[762];B[hk]BL[793];W[gj]WL[759] 11 | ;B[fj]BL[789];W[gk]WL[755];B[gl]BL[785];W[fk]WL[752];B[ek]BL[782];W[fl]WL[748];B[fm]BL[778];W[el]WL[744] 12 | ;B[dl]BL[774];W[em]WL[741]) 13 | 14 | -------------------------------------------------------------------------------- /ladder_suite/ladder/411203.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[adams]PB[Zen-15.7-1c0g]WR[3768?]BR[3236]DT[2018-04-10]PC[(CGOS) 19x19 Computer Go Server]RE[B+Resign]GN[411203] 4 | ;B[pd]BL[894];W[pp]WL[896];B[dc]BL[890];W[dp]WL[892];B[cn]BL[883];W[de]WL[888];B[fq]BL[878];W[dn]WL[884] 5 | ;B[dm]BL[873];W[en]WL[880];B[cp]BL[872];W[cm]WL[876];B[co]BL[867];W[dl]WL[873];B[em]BL[859];W[cl]WL[868] 6 | ;B[dq]BL[853];W[fp]WL[863];B[ep]BL[845];W[fm]WL[859];B[el]BL[840];W[ek]WL[855];B[fl]BL[837];W[eo]WL[852] 7 | ;B[do]BL[831];W[gl]WL[847];B[fk]BL[826]) 8 | 9 | -------------------------------------------------------------------------------- /ladder_suite/ladder/411228.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[adams]PB[Pangu-127]WR[3751?]BR[3715?]DT[2018-04-11]PC[(CGOS) 19x19 Computer Go Server]RE[B+Resign]GN[411228] 4 | ;B[pd]BL[898];W[pp]WL[896];B[dc]BL[886];W[dp]WL[892];B[cn]BL[878];W[de]WL[888];B[fq]BL[868];W[fp]WL[884] 5 | ;B[gp]BL[867];W[fo]WL[880];B[dq]BL[867];W[cq]WL[877];B[eq]BL[867];W[cp]WL[873];B[dm]BL[851];W[dj]WL[869] 6 | ;B[fm]BL[845];W[el]WL[865];B[em]BL[843];W[bo]WL[861];B[nq]BL[832];W[ec]WL[856];B[eb]BL[817];W[ed]WL[852] 7 | ;B[fc]BL[811];W[fb]WL[849];B[gb]BL[810];W[db]WL[845];B[fa]BL[810];W[cc]WL[842];B[qn]BL[809];W[pn]WL[837] 8 | ;B[pm]BL[806];W[on]WL[833];B[qp]BL[800];W[qm]WL[830];B[qo]BL[794];W[pl]WL[826];B[om]BL[788];W[go]WL[822] 9 | ;B[hp]BL[782];W[ho]WL[818];B[ip]BL[782];W[io]WL[814];B[jp]BL[781];W[gl]WL[810];B[fl]BL[774];W[fk]WL[806] 10 | ;B[gk]BL[774];W[hk]WL[802];B[gj]BL[773];W[fj]WL[798];B[cj]BL[767];W[ck]WL[794];B[dk]BL[761];W[dl]WL[790] 11 | ;B[cl]BL[755];W[ek]WL[787];B[bk]BL[755];W[ci]WL[783];B[dk]BL[754];W[nm]WL[778];B[ol]BL[754];W[ck]WL[775] 12 | ;B[ep]BL[752];W[eo]WL[770];B[dk]BL[751];W[ok]WL[767];B[nl]BL[751];W[ml]WL[763];B[nk]BL[744];W[ck]WL[760] 13 | ;B[bj]BL[740];W[bl]WL[755];B[dk]BL[740];W[nj]WL[751];B[mk]BL[740];W[ck]WL[748];B[cm]BL[739];W[bi]WL[744] 14 | ;B[pk]BL[724];W[gi]WL[739];B[hj]BL[718];W[ij]WL[735];B[hi]BL[710];W[hh]WL[731];B[ii]BL[703];W[ji]WL[727] 15 | ;B[ih]BL[701];W[ig]WL[723];B[jh]BL[699];W[kh]WL[719];B[jg]BL[698];W[lk]WL[715];B[oj]BL[691];W[jf]WL[709] 16 | ;B[kg]BL[688];W[lg]WL[706];B[kf]BL[687];W[ke]WL[702];B[lf]BL[687];W[mf]WL[698];B[le]BL[687];W[ld]WL[695] 17 | ;B[me]BL[686];W[ne]WL[691];B[md]BL[686]) 18 | 19 | -------------------------------------------------------------------------------- /ladder_suite/ladder/411295.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[adams]PB[nvwa-new]WR[3780?]BR[3632?]DT[2018-04-11]PC[(CGOS) 19x19 Computer Go Server]RE[B+Resign]GN[411295] 4 | ;B[dp]BL[898];W[pp]WL[896];B[dd]BL[879];W[pd]WL[892];B[qq]BL[860];W[pq]WL[888];B[qp]BL[847];W[qn]WL[885] 5 | ;B[qo]BL[846];W[po]WL[881];B[rn]BL[845];W[qr]WL[878];B[rr]BL[843];W[rm]WL[874];B[pr]BL[830];W[or]WL[870] 6 | ;B[pn]BL[828];W[qm]WL[865];B[qs]BL[826];W[on]WL[862];B[pm]BL[807];W[no]WL[857];B[om]BL[796];W[nm]WL[853] 7 | ;B[pk]BL[787];W[qj]WL[849];B[nl]BL[787];W[mm]WL[845];B[qk]BL[776];W[rk]WL[841];B[rj]BL[775];W[ql]WL[838] 8 | ;B[sk]BL[764];W[rl]WL[834];B[ri]BL[763];W[pl]WL[830];B[ol]BL[753];W[ok]WL[826];B[pj]BL[749];W[pi]WL[822] 9 | ;B[oj]BL[742];W[nk]WL[817];B[ml]BL[741];W[ll]WL[813];B[mk]BL[731];W[nj]WL[809];B[qi]BL[731];W[mj]WL[803] 10 | ;B[lk]BL[720];W[kk]WL[799];B[lj]BL[711];W[li]WL[796];B[kj]BL[707];W[jj]WL[792];B[ki]BL[699];W[oi]WL[789] 11 | ;B[qj]BL[693];W[kh]WL[784];B[ji]BL[684]) 12 | 13 | -------------------------------------------------------------------------------- /ladder_suite/ladder/411342.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[nvwa-new]PB[adams]WR[3626?]BR[3795?]DT[2018-04-11]PC[(CGOS) 19x19 Computer Go Server]RE[W+Resign]GN[411342] 4 | ;B[pp]BL[896];W[dd]WL[898];B[pc]BL[892];W[dp]WL[889];B[pf]BL[888];W[qq]WL[875];B[pq]BL[885];W[qp]WL[863] 5 | ;B[qn]BL[881];W[qo]WL[856];B[po]BL[878];W[rn]WL[855];B[qr]BL[874];W[rr]WL[853];B[ro]BL[870];W[pr]WL[848] 6 | ;B[rq]BL[866];W[qs]WL[847];B[rp]BL[863];W[qr]WL[846];B[rm]BL[859];W[pn]WL[844];B[qm]BL[856];W[nq]WL[842] 7 | ;B[on]BL[850];W[pm]WL[826];B[pl]BL[845];W[om]WL[816];B[np]BL[842];W[mp]WL[816];B[mo]BL[838];W[lp]WL[815] 8 | ;B[lo]BL[834];W[kp]WL[814];B[nm]BL[830];W[ol]WL[801];B[oq]BL[826];W[or]WL[793];B[ok]BL[822];W[nl]WL[785] 9 | ;B[nr]BL[819];W[mq]WL[776];B[ml]BL[815];W[nk]WL[767];B[nj]BL[810];W[mk]WL[761];B[lk]BL[806];W[mj]WL[753] 10 | ;B[mi]BL[803];W[lj]WL[746]) 11 | 12 | -------------------------------------------------------------------------------- /ladder_suite/ladder/411435.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[adams]PB[Pangu-127]WR[3824?]BR[3709]DT[2018-04-11]PC[(CGOS) 19x19 Computer Go Server]RE[B+Resign]GN[411435] 4 | ;B[dp]BL[897];W[dd]WL[896];B[pq]BL[884];W[pd]WL[892];B[qf]BL[878];W[po]WL[888];B[nc]BL[869];W[pf]WL[884] 5 | ;B[pg]BL[867];W[of]WL[880];B[qd]BL[865];W[qg]WL[876];B[qe]BL[860];W[ph]WL[873];B[og]BL[854];W[qh]WL[868] 6 | ;B[pc]BL[853];W[od]WL[864];B[oc]BL[847];W[ng]WL[860];B[oh]BL[842];W[oi]WL[857];B[nh]BL[836];W[mh]WL[853] 7 | ;B[ni]BL[831];W[nj]WL[850];B[mi]BL[825];W[li]WL[846];B[mj]BL[820]) 8 | 9 | -------------------------------------------------------------------------------- /ladder_suite/ladder/411482.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[nvwa-new3]PB[adams]WR[2882?]BR[3818?]DT[2018-04-11]PC[(CGOS) 19x19 Computer Go Server]RE[W+Resign]GN[411482] 4 | ;B[dp]BL[896];W[dd]WL[898];B[qp]BL[892];W[pd]WL[892];B[np]BL[888];W[cq]WL[884];B[cp]BL[884];W[dq]WL[876] 5 | ;B[fq]BL[881];W[eq]WL[871];B[ep]BL[877];W[fr]WL[870];B[bq]BL[874];W[br]WL[870];B[er]BL[869];W[bp]WL[861] 6 | ;B[cr]BL[865];W[aq]WL[860];B[dr]BL[862];W[bq]WL[860];B[gr]BL[858];W[fp]WL[859];B[gq]BL[855];W[cn]WL[858] 7 | ;B[fo]BL[849];W[gp]WL[850];B[hp]BL[844];W[go]WL[842];B[dn]BL[840];W[dm]WL[842];B[em]BL[836];W[dl]WL[841] 8 | ;B[gn]BL[832];W[ho]WL[834];B[co]BL[829];W[bo]WL[827];B[io]BL[824];W[hn]WL[821];B[hm]BL[821];W[in]WL[816] 9 | ;B[jn]BL[817];W[im]WL[816];B[il]BL[813];W[jm]WL[815];B[bn]BL[809];W[cm]WL[807]) 10 | 11 | -------------------------------------------------------------------------------- /ladder_suite/ladder/411518.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[adams]PB[Pangu-127]WR[3817?]BR[3720]DT[2018-04-11]PC[(CGOS) 19x19 Computer Go Server]RE[B+Resign]GN[411518] 4 | ;B[dd]BL[898];W[pd]WL[896];B[cp]BL[887];W[pp]WL[892];B[nq]BL[877];W[ep]WL[888];B[qn]BL[869];W[np]WL[884] 5 | ;B[mp]BL[866];W[no]WL[881];B[pq]BL[863];W[mq]WL[877];B[oq]BL[857];W[lp]WL[873];B[mo]BL[852];W[lq]WL[869] 6 | ;B[qp]BL[852];W[po]WL[865];B[qo]BL[846];W[mn]WL[861];B[lo]BL[841];W[qq]WL[857];B[nn]BL[834];W[on]WL[853] 7 | ;B[nm]BL[830];W[om]WL[849];B[oo]BL[823];W[op]WL[845];B[pn]BL[820];W[oo]WL[842];B[ol]BL[819];W[pm]WL[839] 8 | ;B[pl]BL[808]) 9 | 10 | -------------------------------------------------------------------------------- /ladder_suite/ladder/411565.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[adams]PB[Pangu-139-n3]WR[3811]BR[3617]DT[2018-04-11]PC[(CGOS) 19x19 Computer Go Server]RE[B+Resign]GN[411565] 4 | ;B[dp]BL[898];W[dd]WL[895];B[pq]BL[886];W[pd]WL[891];B[qf]BL[882];W[po]WL[887];B[qo]BL[871];W[qn]WL[883] 5 | ;B[qp]BL[870];W[pn]WL[880];B[nc]BL[860];W[pf]WL[876];B[pg]BL[854];W[of]WL[873];B[qd]BL[853];W[qg]WL[867] 6 | ;B[qe]BL[847];W[ph]WL[864];B[og]BL[841];W[qh]WL[859];B[pc]BL[841];W[oq]WL[856];B[or]BL[834];W[ng]WL[852] 7 | ;B[oh]BL[828];W[pr]WL[848];B[qr]BL[821];W[nr]WL[843];B[ps]BL[819];W[od]WL[840];B[oc]BL[813];W[qc]WL[835] 8 | ;B[rc]BL[810];W[oi]WL[831];B[nh]BL[804];W[mh]WL[828];B[ni]BL[798];W[nj]WL[824];B[mi]BL[791]) 9 | 10 | -------------------------------------------------------------------------------- /ladder_suite/ladder/411578.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[nvwa-new4]PB[adams]WR[3321?]BR[3799]DT[2018-04-11]PC[(CGOS) 19x19 Computer Go Server]RE[W+Resign]GN[411578] 4 | ;B[pp]BL[896];W[dp]WL[898];B[pc]BL[892];W[dd]WL[889];B[pf]BL[888];W[qq]WL[878];B[pq]BL[884];W[qp]WL[869] 5 | ;B[qn]BL[881];W[qo]WL[863];B[po]BL[877];W[rn]WL[863];B[qr]BL[874];W[rr]WL[854];B[ro]BL[869];W[pr]WL[839] 6 | ;B[rq]BL[864];W[qs]WL[838];B[rp]BL[861];W[qr]WL[837];B[rm]BL[858];W[pn]WL[837];B[qm]BL[854];W[nq]WL[836] 7 | ;B[on]BL[849];W[pm]WL[828];B[pl]BL[845];W[om]WL[820];B[np]BL[841];W[mp]WL[820];B[mo]BL[837];W[lp]WL[819] 8 | ;B[nm]BL[833];W[ol]WL[812];B[oq]BL[829];W[or]WL[805];B[ok]BL[825];W[nl]WL[798];B[ml]BL[821];W[nk]WL[792] 9 | ;B[nj]BL[817];W[mk]WL[792];B[lk]BL[813];W[mj]WL[791];B[mq]BL[810];W[nr]WL[782]) 10 | 11 | -------------------------------------------------------------------------------- /ladder_suite/ladder/411644.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[jefferson]PB[Pangu-127]WR[3385?]BR[3729]DT[2018-04-11]PC[(CGOS) 19x19 Computer Go Server]RE[B+Resign]GN[411644] 4 | ;B[dp]BL[898];W[pp]WL[896];B[cd]BL[886];W[pd]WL[892];B[nc]BL[879];W[ed]WL[888];B[qf]BL[871];W[nd]WL[884] 5 | ;B[md]BL[868];W[ne]WL[881];B[pc]BL[867];W[mc]WL[877];B[oc]BL[861];W[ld]WL[873];B[me]BL[856];W[lc]WL[868] 6 | ;B[qd]BL[854];W[pe]WL[864];B[qe]BL[849];W[mf]WL[860];B[le]BL[844];W[ke]WL[856];B[lf]BL[838];W[lg]WL[853] 7 | ;B[kf]BL[833];W[jf]WL[849];B[kg]BL[827];W[kh]WL[845];B[jg]BL[822];W[ig]WL[842];B[jh]BL[818];W[ji]WL[839] 8 | ;B[ih]BL[814]) 9 | 10 | -------------------------------------------------------------------------------- /ladder_suite/ladder/411670.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[nvwa-new3]PB[jefferson]WR[3468?]BR[3495?]DT[2018-04-11]PC[(CGOS) 19x19 Computer Go Server]RE[W+Resign]GN[411670] 4 | ;B[pp]BL[896];W[pd]WL[898];B[dq]BL[892];W[dd]WL[891];B[dn]BL[888];W[qq]WL[883];B[qp]BL[884];W[pq]WL[875] 5 | ;B[nq]BL[881];W[oq]WL[869];B[op]BL[878];W[nr]WL[868];B[rq]BL[874];W[rr]WL[861];B[or]BL[870];W[rp]WL[845] 6 | ;B[qr]BL[865];W[sq]WL[845];B[pr]BL[862];W[rq]WL[844];B[mr]BL[858];W[np]WL[844];B[mq]BL[855];W[qn]WL[843] 7 | ;B[no]BL[851];W[mp]WL[835];B[pn]BL[847];W[pm]WL[827];B[lp]BL[841];W[mo]WL[824];B[om]BL[838];W[pl]WL[824] 8 | ;B[mn]BL[833];W[lo]WL[817];B[qo]BL[830];W[ro]WL[810];B[ko]BL[826];W[ln]WL[804];B[lm]BL[822];W[kn]WL[798] 9 | ;B[jn]BL[819];W[km]WL[798];B[kl]BL[815];W[jm]WL[797];B[im]BL[811];W[jl]WL[797];B[jk]BL[807];W[il]WL[796] 10 | ;B[hl]BL[803];W[ik]WL[795];B[ij]BL[799];W[hk]WL[795];B[gk]BL[795];W[hj]WL[794];B[hi]BL[791];W[gj]WL[793] 11 | ;B[fj]BL[788];W[gi]WL[792];B[gh]BL[784];W[fi]WL[791];B[ei]BL[780];W[fh]WL[790];B[fg]BL[776];W[eh]WL[789] 12 | ;B[dh]BL[773];W[eg]WL[788];B[ef]BL[769];W[dg]WL[787];B[cg]BL[765];W[df]WL[783];B[de]BL[760];W[cf]WL[780] 13 | ;B[qm]BL[756];W[rn]WL[775];B[ql]BL[752];W[ce]WL[764]) 14 | 15 | -------------------------------------------------------------------------------- /ladder_suite/ladder/411851.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[jefferson]PB[Zen-15.7-1c1g]WR[3920?]BR[3746]DT[2018-04-12]PC[(CGOS) 19x19 Computer Go Server]RE[B+Resign]GN[411851] 4 | ;B[pd]BL[895];W[pp]WL[896];B[dc]BL[890];W[dp]WL[892];B[cn]BL[884];W[de]WL[888];B[fq]BL[879];W[dn]WL[884] 5 | ;B[dm]BL[875];W[en]WL[881];B[cp]BL[874];W[cm]WL[877];B[co]BL[869];W[dl]WL[873];B[em]BL[865];W[cl]WL[869] 6 | ;B[fm]BL[862];W[fn]WL[865];B[dq]BL[856];W[gm]WL[861];B[ek]BL[853];W[ci]WL[858];B[gn]BL[848];W[hm]WL[853] 7 | ;B[fo]BL[844];W[el]WL[849];B[fl]BL[840];W[fk]WL[846];B[gl]BL[838];W[hn]WL[843];B[go]BL[833];W[gk]WL[838] 8 | ;B[hl]BL[831];W[il]WL[834];B[hk]BL[825];W[hj]WL[830];B[ik]BL[820];W[jk]WL[827];B[ij]BL[814];W[ii]WL[824] 9 | ;B[jj]BL[812];W[kj]WL[820];B[ji]BL[806];W[jh]WL[817];B[ki]BL[801]) 10 | 11 | -------------------------------------------------------------------------------- /ladder_suite/ladder/411881.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[jefferson]PB[Zen-15.9-1c1g]WR[3850?]BR[3567]DT[2018-04-12]PC[(CGOS) 19x19 Computer Go Server]RE[B+Resign]GN[411881] 4 | ;B[pd]BL[895];W[dd]WL[896];B[qp]BL[892];W[dp]WL[892];B[fq]BL[887];W[op]WL[888];B[cn]BL[881];W[fp]WL[884] 5 | ;B[gp]BL[877];W[fo]WL[880];B[dq]BL[875];W[gq]WL[877];B[eq]BL[869];W[hp]WL[873];B[go]BL[865];W[hq]WL[868] 6 | ;B[cp]BL[862];W[dn]WL[864];B[do]BL[857];W[gn]WL[861];B[ho]BL[852];W[eo]WL[857];B[ep]BL[848];W[io]WL[853] 7 | ;B[hn]BL[844];W[hm]WL[849];B[in]BL[839];W[jn]WL[845];B[im]BL[834];W[il]WL[842];B[jm]BL[829]) 8 | 9 | -------------------------------------------------------------------------------- /ladder_suite/ladder/411899.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[jefferson]PB[Pangu-139-n3]WR[3791?]BR[3629]DT[2018-04-12]PC[(CGOS) 19x19 Computer Go Server]RE[B+Resign]GN[411899] 4 | ;B[dp]BL[899];W[dd]WL[896];B[pq]BL[887];W[pd]WL[892];B[qf]BL[883];W[po]WL[888];B[qo]BL[867];W[qn]WL[884] 5 | ;B[qp]BL[866];W[pn]WL[881];B[nc]BL[859];W[pf]WL[877];B[pg]BL[850];W[of]WL[872];B[qd]BL[850];W[qg]WL[868] 6 | ;B[qe]BL[844];W[ph]WL[864];B[og]BL[839];W[qh]WL[860];B[pc]BL[837];W[nd]WL[856];B[od]BL[830];W[ng]WL[852] 7 | ;B[oh]BL[824];W[oi]WL[848];B[nh]BL[819];W[mh]WL[845];B[ni]BL[813];W[oe]WL[841];B[pe]BL[807];W[nj]WL[837] 8 | ;B[mi]BL[801]) 9 | 10 | -------------------------------------------------------------------------------- /ladder_suite/ladder/412038.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[nvwa-lv3-2]PB[jefferson]WR[3654?]BR[3820?]DT[2018-04-12]PC[(CGOS) 19x19 Computer Go Server]RE[W+Resign]GN[412038] 4 | ;B[dp]BL[896];W[pd]WL[898];B[pq]BL[892];W[dd]WL[892];B[pn]BL[889];W[cq]WL[885];B[cp]BL[885];W[dq]WL[877] 5 | ;B[fq]BL[881];W[eq]WL[872];B[ep]BL[878];W[fr]WL[871];B[bq]BL[874];W[br]WL[865];B[er]BL[871];W[bp]WL[853] 6 | ;B[cr]BL[866];W[aq]WL[853];B[dr]BL[863];W[bq]WL[853];B[gr]BL[859];W[fp]WL[852];B[gq]BL[856];W[cn]WL[852] 7 | ;B[fo]BL[852];W[gp]WL[844];B[dn]BL[846];W[dm]WL[836];B[hp]BL[843];W[go]WL[834];B[em]BL[839];W[dl]WL[834] 8 | ;B[gn]BL[835];W[ho]WL[827];B[co]BL[831];W[bo]WL[820];B[io]BL[827];W[hn]WL[813];B[hm]BL[824];W[in]WL[810] 9 | ;B[jn]BL[820];W[im]WL[809];B[il]BL[817];W[jm]WL[809];B[cm]BL[812];W[bn]WL[802]) 10 | 11 | -------------------------------------------------------------------------------- /ladder_suite/ladder/412092.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[jefferson]PB[Zen-15.9-1c1g]WR[3823?]BR[3567]DT[2018-04-12]PC[(CGOS) 19x19 Computer Go Server]RE[B+Resign]GN[412092] 4 | ;B[pd]BL[895];W[dd]WL[896];B[qp]BL[893];W[dp]WL[892];B[fq]BL[888];W[op]WL[888];B[cn]BL[883];W[fp]WL[885] 5 | ;B[gp]BL[879];W[fo]WL[881];B[dq]BL[878];W[gq]WL[877];B[eq]BL[873];W[hp]WL[873];B[go]BL[869];W[hq]WL[869] 6 | ;B[cp]BL[865];W[gn]WL[865];B[ho]BL[860];W[io]WL[861];B[hn]BL[856];W[do]WL[858];B[co]BL[853];W[hm]WL[854] 7 | ;B[in]BL[848];W[jn]WL[850];B[im]BL[844];W[il]WL[847];B[jm]BL[839]) 8 | 9 | -------------------------------------------------------------------------------- /ladder_suite/ladder/412141.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[jefferson]PB[Zen-15.7-1c0g]WR[3831?]BR[3231]DT[2018-04-12]PC[(CGOS) 19x19 Computer Go Server]RE[B+Resign]GN[412141] 4 | ;B[pd]BL[894];W[dd]WL[896];B[qp]BL[893];W[dp]WL[892];B[fq]BL[888];W[op]WL[888];B[cn]BL[883];W[fp]WL[884] 5 | ;B[gp]BL[878];W[fo]WL[881];B[dq]BL[875];W[gq]WL[877];B[eq]BL[870];W[hp]WL[873];B[go]BL[865];W[hq]WL[869] 6 | ;B[cp]BL[859];W[gn]WL[865];B[ho]BL[854];W[do]WL[861];B[co]BL[852];W[cq]WL[857];B[fn]BL[846];W[fm]WL[853] 7 | ;B[en]BL[844];W[io]WL[850];B[hn]BL[838];W[dn]WL[846];B[dm]BL[832];W[in]WL[842];B[hm]BL[827];W[hl]WL[838] 8 | ;B[im]BL[821]) 9 | 10 | -------------------------------------------------------------------------------- /ladder_suite/ladder/412181.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[nvwa-lv3-2]PB[jefferson]WR[3733?]BR[3803?]DT[2018-04-12]PC[(CGOS) 19x19 Computer Go Server]RE[W+Resign]GN[412181] 4 | ;B[dp]BL[896];W[pd]WL[898];B[pq]BL[892];W[dd]WL[891];B[pn]BL[889];W[cq]WL[883];B[cp]BL[885];W[dq]WL[876] 5 | ;B[fq]BL[881];W[eq]WL[871];B[ep]BL[878];W[fr]WL[870];B[bq]BL[875];W[br]WL[863];B[er]BL[871];W[bp]WL[848] 6 | ;B[cr]BL[866];W[aq]WL[848];B[dr]BL[862];W[bq]WL[848];B[gr]BL[859];W[fp]WL[848];B[gq]BL[856];W[cn]WL[847] 7 | ;B[fo]BL[852];W[gp]WL[840];B[dn]BL[848];W[dm]WL[832];B[hp]BL[842];W[go]WL[831];B[em]BL[839];W[dl]WL[831] 8 | ;B[el]BL[835];W[dk]WL[830];B[gn]BL[831];W[ho]WL[823];B[io]BL[827];W[hn]WL[817];B[co]BL[824];W[bo]WL[810] 9 | ;B[bn]BL[819];W[cm]WL[804];B[hm]BL[815];W[in]WL[798];B[jn]BL[812];W[im]WL[796]) 10 | 11 | -------------------------------------------------------------------------------- /ladder_suite/ladder/412280.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[jefferson]PB[Zen-15.9-1c1g]WR[3832?]BR[3570]DT[2018-04-12]PC[(CGOS) 19x19 Computer Go Server]RE[B+Resign]GN[412280] 4 | ;B[pd]BL[895];W[dd]WL[896];B[qp]BL[892];W[dp]WL[892];B[fq]BL[887];W[op]WL[888];B[cn]BL[882];W[fp]WL[884] 5 | ;B[gp]BL[878];W[fo]WL[881];B[dq]BL[876];W[gq]WL[877];B[eq]BL[872];W[hp]WL[874];B[go]BL[867];W[hq]WL[869] 6 | ;B[cp]BL[863];W[gn]WL[865];B[ho]BL[858];W[do]WL[861];B[co]BL[855];W[io]WL[857];B[hn]BL[853];W[hm]WL[854] 7 | ;B[in]BL[848];W[jn]WL[850];B[im]BL[843];W[il]WL[847];B[jm]BL[838];W[km]WL[843];B[jl]BL[834];W[jk]WL[840] 8 | ;B[kl]BL[829];W[ll]WL[837];B[kk]BL[825]) 9 | 10 | -------------------------------------------------------------------------------- /ladder_suite/ladder/412313.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[nvwa-lv3-3]PB[jefferson]WR[3665?]BR[3829?]DT[2018-04-12]PC[(CGOS) 19x19 Computer Go Server]RE[W+Resign]GN[412313] 4 | ;B[pd]BL[896];W[dd]WL[898];B[qp]BL[892];W[dp]WL[893];B[np]BL[888];W[qc]WL[886];B[pc]BL[884];W[qd]WL[879] 5 | ;B[qf]BL[881];W[qe]WL[873];B[pe]BL[878];W[rf]WL[873];B[qb]BL[874];W[rb]WL[869];B[re]BL[871];W[pb]WL[859] 6 | ;B[rc]BL[865];W[qa]WL[859];B[rd]BL[862];W[qb]WL[858];B[rg]BL[859];W[pf]WL[858];B[qg]BL[855];W[nc]WL[858] 7 | ;B[of]BL[851];W[pg]WL[851];B[nd]BL[847];W[md]WL[844];B[ph]BL[842];W[og]WL[844];B[me]BL[839];W[ld]WL[843] 8 | ;B[le]BL[834];W[kd]WL[843];B[ng]BL[831];W[oh]WL[836];B[oi]BL[827];W[nh]WL[830];B[oc]BL[823];W[ob]WL[823] 9 | ;B[mh]BL[819];W[ni]WL[816];B[nj]BL[815];W[mi]WL[815];B[li]BL[811];W[mj]WL[815];B[mc]BL[808];W[nb]WL[806] 10 | ;B[mk]BL[803];W[lj]WL[805]) 11 | 12 | -------------------------------------------------------------------------------- /ladder_suite/ladder/412407.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[jefferson]PB[Pangu-127]WR[3800?]BR[3731]DT[2018-04-12]PC[(CGOS) 19x19 Computer Go Server]RE[B+Resign]GN[412407] 4 | ;B[dp]BL[898];W[pp]WL[896];B[cd]BL[887];W[pd]WL[892];B[nc]BL[879];W[ed]WL[888];B[qf]BL[870];W[nd]WL[884] 5 | ;B[md]BL[866];W[ne]WL[880];B[pc]BL[862];W[mc]WL[876];B[oc]BL[857];W[ld]WL[872];B[me]BL[852];W[lc]WL[868] 6 | ;B[qd]BL[850];W[pe]WL[864];B[qe]BL[845];W[mf]WL[860];B[le]BL[840];W[ke]WL[856];B[lf]BL[834];W[lg]WL[852] 7 | ;B[kf]BL[829];W[jf]WL[848];B[kg]BL[824];W[kh]WL[845];B[jg]BL[819];W[ig]WL[841];B[jh]BL[816]) 8 | 9 | -------------------------------------------------------------------------------- /ladder_suite/ladder/412432.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[JingSiWeiqi]PB[jefferson]WR[3534]BR[3786?]DT[2018-04-13]PC[(CGOS) 19x19 Computer Go Server]RE[W+Resign]GN[412432] 4 | ;B[dd]BL[896];W[pp]WL[871];B[qd]BL[892];W[dp]WL[852];B[nd]BL[888];W[cc]WL[838];B[cd]BL[884];W[dc]WL[825] 5 | ;B[fc]BL[880];W[ec]WL[811];B[ed]BL[877];W[fb]WL[797];B[bc]BL[873];W[bb]WL[784];B[gb]BL[870];W[bd]WL[768] 6 | ;B[fd]BL[865];W[be]WL[755];B[eb]BL[862];W[db]WL[743];B[qp]BL[858];W[qq]WL[731];B[qo]BL[853];W[po]WL[711] 7 | ;B[rq]BL[848];W[pq]WL[693];B[qm]BL[845];W[pn]WL[678];B[rl]BL[840];W[rr]WL[662];B[ol]BL[835];W[qf]WL[650] 8 | ;B[ph]BL[831];W[qc]WL[639];B[pc]BL[828];W[pd]WL[628];B[qb]BL[824];W[rc]WL[618];B[pe]BL[820];W[od]WL[608] 9 | ;B[oc]BL[815];W[oe]WL[598];B[rd]BL[812];W[rb]WL[588];B[ra]BL[807];W[pb]WL[578];B[sb]BL[804];W[qa]WL[568] 10 | ;B[sc]BL[799];W[sa]WL[559];B[of]BL[796];W[ne]WL[550];B[me]BL[792];W[nf]WL[540];B[ng]BL[788];W[mf]WL[531] 11 | ;B[lf]BL[784];W[mg]WL[523];B[mh]BL[781];W[lg]WL[513];B[kg]BL[777];W[lh]WL[503];B[li]BL[774];W[kh]WL[495] 12 | ;B[jh]BL[771];W[ki]WL[486];B[kj]BL[767];W[ji]WL[478]) 13 | 14 | -------------------------------------------------------------------------------- /ladder_suite/ladder/412440.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[nvwa-lv3-2]PB[jefferson]WR[3629?]BR[3767?]DT[2018-04-13]PC[(CGOS) 19x19 Computer Go Server]RE[W+Resign]GN[412440] 4 | ;B[pp]BL[894];W[dd]WL[898];B[cp]BL[890];W[pd]WL[891];B[fp]BL[886];W[qq]WL[883];B[qp]BL[882];W[pq]WL[875] 5 | ;B[nq]BL[879];W[oq]WL[871];B[op]BL[875];W[nr]WL[871];B[rq]BL[872];W[rr]WL[866];B[mr]BL[868];W[rp]WL[861] 6 | ;B[np]BL[864];W[ro]WL[856];B[or]BL[860];W[pr]WL[850];B[cd]BL[856];W[cc]WL[842];B[ce]BL[851];W[de]WL[842] 7 | ;B[bc]BL[847];W[dc]WL[841];B[cg]BL[843];W[df]WL[839];B[bh]BL[839];W[bb]WL[832];B[eh]BL[834];W[cn]WL[826] 8 | ;B[dl]BL[830];W[cq]WL[819];B[dq]BL[826];W[dp]WL[812];B[cr]BL[822];W[bq]WL[806];B[do]BL[818];W[ep]WL[806] 9 | ;B[eq]BL[814];W[eo]WL[800];B[bp]BL[810];W[br]WL[798];B[bs]BL[806];W[dr]WL[791];B[ar]BL[802];W[cs]WL[785] 10 | ;B[aq]BL[798];W[as]WL[785];B[fo]BL[794];W[en]WL[784];B[bs]BL[790];W[cr]WL[784];B[er]BL[787];W[as]WL[784] 11 | ;B[em]BL[783];W[ap]WL[776];B[dn]BL[778];W[fn]WL[776];B[co]BL[775];W[fq]WL[776];B[fr]BL[771];W[gq]WL[776] 12 | ;B[gr]BL[767];W[hq]WL[775];B[hr]BL[763];W[iq]WL[775];B[gn]BL[759];W[fm]WL[768];B[fl]BL[755];W[gm]WL[760] 13 | ;B[hm]BL[751];W[gl]WL[756];B[gk]BL[744];W[hl]WL[751];B[il]BL[741];W[hk]WL[750];B[hj]BL[737];W[ik]WL[749] 14 | ;B[jk]BL[734];W[ij]WL[749];B[ii]BL[730];W[jj]WL[749];B[kj]BL[727];W[ji]WL[749];B[jh]BL[723];W[ki]WL[748] 15 | ;B[li]BL[720];W[kh]WL[748];B[kg]BL[716];W[lh]WL[748];B[mh]BL[713];W[lg]WL[747];B[lf]BL[709];W[mg]WL[744] 16 | ;B[ng]BL[706];W[mf]WL[743];B[me]BL[702];W[nf]WL[739];B[of]BL[698];W[ne]WL[737];B[nd]BL[693];W[oe]WL[729] 17 | ) 18 | 19 | -------------------------------------------------------------------------------- /ladder_suite/ladder/412477.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[jefferson]PB[Pangu-139-n3]WR[3774?]BR[3655]DT[2018-04-13]PC[(CGOS) 19x19 Computer Go Server]RE[B+Resign]GN[412477] 4 | ;B[pd]BL[898];W[pp]WL[896];B[dc]BL[884];W[dp]WL[891];B[cn]BL[881];W[de]WL[887];B[ce]BL[868];W[cf]WL[883] 5 | ;B[cd]BL[867];W[df]WL[880];B[fq]BL[863];W[dn]WL[876];B[dm]BL[857];W[en]WL[872];B[cp]BL[856];W[cm]WL[867] 6 | ;B[co]BL[850];W[dl]WL[864];B[em]BL[845];W[cl]WL[859];B[dq]BL[844];W[fp]WL[855];B[ep]BL[837];W[fm]WL[851] 7 | ;B[el]BL[831];W[ek]WL[847];B[fl]BL[825];W[gl]WL[843];B[fk]BL[819];W[eo]WL[840];B[do]BL[813];W[fj]WL[835] 8 | ;B[gk]BL[808];W[hk]WL[831];B[gj]BL[802]) 9 | 10 | -------------------------------------------------------------------------------- /ladder_suite/ladder/413022.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[qadams]PB[Leela-HX01]WR[3935?]BR[3839?]DT[2018-04-14]PC[(CGOS) 19x19 Computer Go Server]RE[B+Resign]GN[413022] 4 | ;B[dc]BL[887];W[pd]WL[896];B[qp]BL[875];W[dp]WL[892];B[qc]BL[865];W[qd]WL[888];B[pc]BL[860];W[nc]WL[884] 5 | ;B[oc]BL[855];W[od]WL[880];B[nb]BL[853];W[ce]WL[877];B[fd]BL[848];W[op]WL[873];B[oq]BL[841];W[nq]WL[869] 6 | ;B[pq]BL[838];W[np]WL[866];B[qn]BL[835];W[gq]WL[862];B[hp]BL[824];W[gp]WL[857];B[ho]BL[816];W[go]WL[853] 7 | ;B[lq]BL[806];W[lp]WL[849];B[kp]BL[801];W[lo]WL[845];B[ko]BL[796];W[kn]WL[842];B[ln]BL[791];W[kq]WL[838] 8 | ;B[jq]BL[788];W[kr]WL[835];B[mn]BL[787];W[lr]WL[831];B[mp]BL[786];W[mq]WL[826];B[mo]BL[784];W[po]WL[823] 9 | ;B[lq]BL[778];W[qo]WL[818];B[ro]BL[775];W[rn]WL[814];B[rp]BL[772];W[qm]WL[810];B[pn]BL[767];W[jr]WL[806] 10 | ;B[on]BL[756];W[qi]WL[803];B[ci]BL[747];W[rl]WL[799];B[bo]BL[737];W[cp]WL[795];B[cl]BL[732];W[cc]WL[791] 11 | ;B[cb]BL[729];W[dd]WL[787];B[ec]BL[722];W[ch]WL[784];B[bh]BL[715];W[bg]WL[779];B[cg]BL[709];W[dh]WL[775] 12 | ;B[bf]BL[707];W[bi]WL[772];B[ag]BL[702];W[cj]WL[768];B[di]BL[697];W[bb]WL[763];B[bc]BL[692];W[bd]WL[760] 13 | ;B[cd]BL[687];W[md]WL[755];B[mb]BL[677];W[cc]WL[752];B[ne]BL[673];W[nd]WL[748];B[cd]BL[669];W[rc]WL[744] 14 | ;B[rb]BL[666];W[cc]WL[740];B[pi]BL[660];W[ac]WL[736];B[qj]BL[655];W[pj]WL[732];B[pk]BL[653];W[oj]WL[728] 15 | ;B[qk]BL[650];W[ok]WL[724];B[qh]BL[644];W[ri]WL[720];B[rh]BL[642];W[ei]WL[717];B[dj]BL[637];W[oi]WL[712] 16 | ;B[ph]BL[633];W[rj]WL[708];B[rk]BL[628];W[pl]WL[704];B[si]BL[623];W[dk]WL[700];B[ej]BL[619];W[fj]WL[696] 17 | ;B[ek]BL[615];W[el]WL[693];B[fk]BL[611];W[gk]WL[689];B[fl]BL[607];W[fm]WL[685];B[gl]BL[605];W[hl]WL[681] 18 | ;B[gm]BL[603];W[ql]WL[677];B[sj]BL[599];W[hm]WL[673];B[gn]BL[595]) 19 | 20 | -------------------------------------------------------------------------------- /ladder_suite/ladder/414239.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[madison]PB[Zen-15.7-1c0g]WR[3817]BR[3223]DT[2018-04-16]PC[(CGOS) 19x19 Computer Go Server]RE[B+Resign]GN[414239] 4 | ;B[pd]BL[895];W[dp]WL[896];B[qp]BL[890];W[dd]WL[892];B[fq]BL[886];W[op]WL[888];B[cn]BL[881];W[fp]WL[884] 5 | ;B[gp]BL[877];W[fo]WL[881];B[dq]BL[875];W[gq]WL[877];B[eq]BL[870];W[hp]WL[873];B[go]BL[865];W[hq]WL[868] 6 | ;B[cp]BL[857];W[gn]WL[865];B[ho]BL[852];W[do]WL[861];B[co]BL[850];W[cq]WL[857];B[fn]BL[844];W[en]WL[853] 7 | ;B[fm]BL[840];W[em]WL[849];B[eo]BL[835]) 8 | 9 | -------------------------------------------------------------------------------- /ladder_suite/ladder/415297.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[ybot-3.4]PB[monroe]WR[2907?]BR[3379?]DT[2018-04-19]PC[(CGOS) 19x19 Computer Go Server]RE[W+Resign]GN[415297] 4 | ;B[pd]BL[895];W[dd]WL[895];B[pq]BL[891];W[dp]WL[893];B[pn]BL[887];W[qf]WL[888];B[qh]BL[882];W[qd]WL[885] 5 | ;B[qc]BL[878];W[pc]WL[885];B[od]BL[874];W[qb]WL[880];B[rc]BL[869];W[rd]WL[880];B[pb]BL[865];W[oc]WL[880] 6 | ;B[rb]BL[861];W[ob]WL[879];B[qa]BL[857];W[of]WL[878];B[nc]BL[852];W[nb]WL[874];B[mc]BL[848];W[nd]WL[870] 7 | ;B[ne]BL[843];W[md]WL[867];B[oe]BL[839];W[lc]WL[865];B[oh]BL[835];W[ng]WL[862];B[me]BL[830];W[ld]WL[862] 8 | ;B[le]BL[826];W[ke]WL[861];B[lg]BL[821];W[kf]WL[861];B[lf]BL[817];W[nh]WL[860];B[oj]BL[813];W[ni]WL[851] 9 | ;B[oi]BL[808];W[kh]WL[843];B[lh]BL[804];W[li]WL[838];B[kg]BL[799];W[jg]WL[838];B[ki]BL[795];W[jh]WL[832] 10 | ;B[mi]BL[791];W[lj]WL[828];B[mj]BL[787];W[nj]WL[828];B[mk]BL[782];W[nk]WL[828];B[kj]BL[768];W[lk]WL[821] 11 | ;B[ll]BL[763];W[kk]WL[815];B[ml]BL[759];W[mh]WL[813];B[pf]BL[754];W[pg]WL[811];B[pe]BL[750];W[qg]WL[811] 12 | ;B[og]BL[745];W[nf]WL[811];B[ok]BL[741];W[nl]WL[810];B[ol]BL[737];W[nm]WL[803];B[mb]BL[732];W[lb]WL[796] 13 | ;B[oa]BL[728];W[ma]WL[789]) 14 | 15 | -------------------------------------------------------------------------------- /ladder_suite/ladder/415520.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[jackson]PB[Zen-15.7p-1c1g]WR[3649?]BR[3516]DT[2018-04-19]PC[(CGOS) 19x19 Computer Go Server]RE[B+Time]GN[415520] 4 | ;B[qc]BL[895];W[dp]WL[894];B[dc]BL[887];W[pp]WL[889];B[cn]BL[882];W[pd]WL[883];B[qd]BL[874];W[pe]WL[878] 5 | ;B[ob]BL[873];W[ce]WL[872];B[fq]BL[867];W[dn]WL[867];B[dm]BL[863];W[en]WL[862];B[cp]BL[862];W[cm]WL[858] 6 | ;B[co]BL[857];W[dl]WL[854];B[dq]BL[856];W[ed]WL[849];B[ec]BL[851];W[fd]WL[844];B[gc]BL[850];W[qe]WL[840] 7 | ;B[nd]BL[842];W[gd]WL[835];B[em]BL[834];W[cl]WL[830];B[hc]BL[830];W[fm]WL[826];B[el]BL[825];W[ep]WL[822] 8 | ;B[eq]BL[821];W[ek]WL[818];B[fl]BL[817];W[pc]WL[813];B[pb]BL[811];W[qb]WL[809];B[rb]BL[806];W[rc]WL[804] 9 | ;B[rd]BL[801]) 10 | 11 | -------------------------------------------------------------------------------- /ladder_suite/ladder/415643.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[jackson]PB[Zen-15.7-1c1g]WR[3723?]BR[3595]DT[2018-04-19]PC[(CGOS) 19x19 Computer Go Server]RE[B+Resign]GN[415643] 4 | ;B[pd]BL[895];W[qc]WL[895];B[pc]BL[890];W[qd]WL[891];B[qf]BL[889];W[qe]WL[887];B[pe]BL[885];W[pf]WL[882] 5 | ;B[qg]BL[881];W[pb]WL[877];B[ob]BL[880];W[qb]WL[873];B[nc]BL[879];W[of]WL[868];B[pi]BL[878];W[pp]WL[864] 6 | ;B[kd]BL[869];W[dd]WL[859];B[fc]BL[861];W[dp]WL[854];B[cf]BL[855];W[df]WL[850];B[dg]BL[851];W[ef]WL[846] 7 | ;B[cd]BL[850];W[cg]WL[841];B[ce]BL[841];W[dh]WL[837];B[dc]BL[839];W[eg]WL[833];B[qn]BL[834];W[pn]WL[827] 8 | ;B[pm]BL[828];W[on]WL[823];B[qp]BL[818];W[qm]WL[818];B[qo]BL[813];W[pl]WL[814];B[om]BL[807];W[ph]WL[809] 9 | ;B[pg]BL[798];W[nm]WL[803];B[ol]BL[792];W[ok]WL[799];B[nl]BL[786];W[og]WL[794];B[oh]BL[783];W[ml]WL[790] 10 | ;B[nk]BL[777];W[nj]WL[785];B[mk]BL[771];W[lk]WL[781];B[mj]BL[764];W[nh]WL[776];B[qh]BL[760];W[mi]WL[771] 11 | ;B[lj]BL[754];W[kj]WL[766];B[li]BL[747];W[lh]WL[762];B[ki]BL[745];W[ji]WL[758];B[kh]BL[738];W[kg]WL[753] 12 | ;B[jh]BL[736];W[ih]WL[748];B[jg]BL[730];W[jf]WL[744];B[ig]BL[726];W[hg]WL[739];B[if]BL[721];W[ie]WL[735] 13 | ;B[hf]BL[717];W[gf]WL[730];B[he]BL[712];W[hd]WL[726];B[ge]BL[711];W[gd]WL[721];B[fe]BL[709]) 14 | 15 | -------------------------------------------------------------------------------- /ladder_suite/ladder/416911.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[Zen-15.7-1c0g]PB[buren]WR[3214]BR[3770?]DT[2018-04-22]PC[(CGOS) 19x19 Computer Go Server]RE[W+Resign]GN[416911] 4 | ;B[dp]BL[895];W[pp]WL[894];B[cd]BL[891];W[pc]WL[893];B[ed]BL[886];W[jd]WL[885];B[qe]BL[882];W[ph]WL[877] 5 | ;B[qn]BL[877];W[ql]WL[871];B[qj]BL[872];W[pj]WL[862];B[pi]BL[868];W[qi]WL[858];B[oi]BL[864];W[rj]WL[857] 6 | ;B[qh]BL[859];W[qk]WL[856];B[ri]BL[855];W[qj]WL[854];B[rg]BL[850];W[oh]WL[845];B[nh]BL[845];W[ni]WL[841] 7 | ;B[oj]BL[841];W[ng]WL[840];B[mh]BL[837];W[mi]WL[839];B[mg]BL[832];W[ok]WL[833];B[nj]BL[827];W[mj]WL[827] 8 | ;B[nk]BL[823];W[nl]WL[822];B[mk]BL[818];W[lk]WL[817];B[ml]BL[814];W[mm]WL[811];B[ll]BL[810];W[kl]WL[806] 9 | ;B[lm]BL[806];W[ln]WL[800];B[km]BL[801];W[jm]WL[795];B[kn]BL[797];W[ko]WL[789];B[jn]BL[793];W[in]WL[788] 10 | ;B[jo]BL[789];W[jp]WL[782];B[io]BL[784];W[ho]WL[780];B[ip]BL[780];W[iq]WL[778]) 11 | 12 | -------------------------------------------------------------------------------- /ladder_suite/ladder/417459.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[Zen-15.7p-1c1g]PB[buren]WR[3516]BR[3840]DT[2018-04-23]PC[(CGOS) 19x19 Computer Go Server]RE[W+Resign]GN[417459] 4 | ;B[dd]BL[895];W[pc]WL[894];B[pp]BL[891];W[dq]WL[889];B[qe]BL[887];W[co]WL[887];B[nd]BL[882];W[od]WL[884] 5 | ;B[oe]BL[878];W[nc]WL[883];B[md]BL[874];W[mc]WL[882];B[ld]BL[870];W[lc]WL[881];B[kd]BL[865];W[jc]WL[880] 6 | ;B[qn]BL[861];W[jq]WL[872];B[mq]BL[856];W[pj]WL[865];B[dn]BL[852];W[do]WL[859];B[fn]BL[848];W[qg]WL[850] 7 | ;B[eq]BL[843];W[fo]WL[841];B[dr]BL[839];W[cq]WL[840];B[hq]BL[835];W[go]WL[836];B[ip]BL[830];W[lp]WL[833] 8 | ;B[mp]BL[826];W[ln]WL[832];B[fr]BL[821];W[in]WL[824];B[cj]BL[817];W[qq]WL[816];B[pq]BL[812];W[og]WL[807] 9 | ;B[cn]BL[808];W[nf]WL[799];B[en]BL[804];W[ep]WL[792];B[jn]BL[799];W[fq]WL[784];B[er]BL[795];W[gq]WL[781] 10 | ;B[gr]BL[791];W[io]WL[779];B[jp]BL[786];W[jo]WL[778];B[ko]BL[782];W[kp]WL[770];B[lo]BL[778];W[mo]WL[763] 11 | ;B[kn]BL[773];W[km]WL[755];B[jm]BL[769];W[jl]WL[748];B[im]BL[765];W[hm]WL[741];B[il]BL[761];W[ik]WL[734] 12 | ;B[hl]BL[757];W[gl]WL[726];B[hk]BL[753];W[hj]WL[720];B[gk]BL[749];W[fk]WL[718];B[gj]BL[745];W[gi]WL[716] 13 | ;B[fj]BL[741];W[ej]WL[714];B[fi]BL[737];W[fh]WL[712];B[ei]BL[732];W[di]WL[710];B[eh]BL[728];W[eg]WL[708] 14 | ;B[dh]BL[724];W[ch]WL[707];B[dg]BL[719];W[df]WL[705];B[cg]BL[715];W[bg]WL[703]) 15 | 16 | -------------------------------------------------------------------------------- /ladder_suite/ladder/417839.sgf: -------------------------------------------------------------------------------- 1 | (;GM[1]FF[4]CA[UTF-8] 2 | RU[Chinese]SZ[19]KM[7.5]TM[900] 3 | PW[harrison]PB[Zen-15.9-1c1g]WR[3244?]BR[3542]DT[2018-04-24]PC[(CGOS) 19x19 Computer Go Server]RE[B+Resign]GN[417839] 4 | ;B[qd]BL[895];W[dd]WL[895];B[pq]BL[890];W[dp]WL[891];B[fc]BL[889];W[po]WL[886];B[cf]BL[885];W[df]WL[882] 5 | ;B[dg]BL[884];W[ef]WL[878];B[cd]BL[882];W[cg]WL[874];B[ce]BL[878];W[dh]WL[869];B[eg]BL[873];W[ch]WL[865] 6 | ;B[dc]BL[870];W[fg]WL[860];B[eh]BL[865];W[ei]WL[855];B[fh]BL[861];W[ed]WL[851];B[ec]BL[859];W[gh]WL[846] 7 | ;B[fi]BL[854]) 8 | 9 | -------------------------------------------------------------------------------- /ladder_suite/ladder_magic_list: -------------------------------------------------------------------------------- 1 | 406958.sgf 15 2 | 406959.sgf 30 3 | 406959.sgf 32 4 | 406996.sgf 15 5 | 407143.sgf 19 6 | 407203.sgf 15 7 | 407248.sgf 15 8 | 407302.sgf 15 9 | 407354.sgf 19 10 | 407482.sgf 15 11 | 407493.sgf 30 12 | 407493.sgf 32 13 | 407541.sgf 15 14 | 407559.sgf 30 15 | 407559.sgf 32 16 | 407570.sgf 30 17 | 407570.sgf 32 18 | 407578.sgf 15 19 | 407581.sgf 15 20 | 407882.sgf 15 21 | 407999.sgf 30 22 | 407999.sgf 32 23 | 408042.sgf 19 24 | 408129.sgf 30 25 | 408129.sgf 32 26 | 408137.sgf 19 27 | 408156.sgf 15 28 | 408179.sgf 15 29 | 408188.sgf 15 30 | 408231.sgf 15 31 | 408234.sgf 15 32 | 408345.sgf 19 33 | 408350.sgf 15 34 | 408361.sgf 15 35 | 408551.sgf 15 36 | 408584.sgf 19 37 | 408815.sgf 19 38 | 408866.sgf 15 39 | 409219.sgf 52 40 | 409219.sgf 58 41 | 409252.sgf 15 42 | 409279.sgf 15 43 | 409355.sgf 19 44 | 409399.sgf 17 45 | 409445.sgf 30 46 | 409445.sgf 32 47 | 409445.sgf 34 48 | 409477.sgf 19 49 | 409563.sgf 30 50 | 409563.sgf 32 51 | 409563.sgf 34 52 | 409598.sgf 15 53 | 409600.sgf 19 54 | 409643.sgf 30 55 | 409643.sgf 32 56 | 409643.sgf 34 57 | 409806.sgf 28 58 | 409806.sgf 30 59 | 409806.sgf 32 60 | 409826.sgf 16 61 | 409848.sgf 15 62 | 409856.sgf 15 63 | 409867.sgf 15 64 | 409993.sgf 19 65 | 410034.sgf 19 66 | 410217.sgf 15 67 | 410333.sgf 19 68 | 410605.sgf 15 69 | 410615.sgf 15 70 | 410756.sgf 15 71 | 410807.sgf 15 72 | 410818.sgf 26 73 | 410818.sgf 28 74 | 410991.sgf 19 75 | 411106.sgf 26 76 | 411203.sgf 15 77 | 411435.sgf 15 78 | 411518.sgf 15 79 | 411565.sgf 19 80 | 411578.sgf 26 81 | 411578.sgf 28 82 | 411644.sgf 15 83 | 411851.sgf 15 84 | 411881.sgf 15 85 | 411899.sgf 19 86 | 412038.sgf 26 87 | 412092.sgf 15 88 | 412141.sgf 15 89 | 412181.sgf 26 90 | 412280.sgf 15 91 | 412313.sgf 26 92 | 412407.sgf 15 93 | 412432.sgf 40 94 | 412440.sgf 40 95 | 412477.sgf 19 96 | 413022.sgf 69 97 | 415297.sgf 26 98 | 415520.sgf 27 99 | 415643.sgf 39 100 | 416911.sgf 30 101 | 417459.sgf 56 102 | 417839.sgf 15 103 | -------------------------------------------------------------------------------- /scripts/devmode_set_pythonpath.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | export ELF_DEVELOPMENT_ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )"/.. && pwd )" 4 | export PYTHONPATH="${ELF_DEVELOPMENT_ROOT}"/src_py/:"${ELF_DEVELOPMENT_ROOT}"/build/elf/:"${ELF_DEVELOPMENT_ROOT}"/build/elfgames/go/:${PYTHONPATH} 5 | -------------------------------------------------------------------------------- /scripts/elfgames/go/df_console.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # Copyright (c) 2018-present, Facebook, Inc. 4 | # All rights reserved. 5 | # 6 | # This source code is licensed under the BSD-style license found in the 7 | # LICENSE file in the root directory of this source tree. 8 | 9 | import os 10 | import sys 11 | 12 | import torch 13 | 14 | from console_lib import GoConsoleGTP 15 | from rlpytorch import Evaluator, load_env 16 | 17 | 18 | def main(): 19 | print('Python version:', sys.version) 20 | print('PyTorch version:', torch.__version__) 21 | print('CUDA version', torch.version.cuda) 22 | print('Conda env:', os.environ.get("CONDA_DEFAULT_ENV", "")) 23 | 24 | additional_to_load = { 25 | 'evaluator': ( 26 | Evaluator.get_option_spec(), 27 | lambda object_map: Evaluator(object_map, stats=None)), 28 | } 29 | 30 | # Set game to online model. 31 | env = load_env( 32 | os.environ, 33 | overrides={ 34 | 'num_games': 1, 35 | 'greedy': True, 36 | 'T': 1, 37 | 'model': 'online', 38 | 'additional_labels': ['aug_code', 'move_idx'], 39 | }, 40 | additional_to_load=additional_to_load) 41 | 42 | evaluator = env['evaluator'] 43 | 44 | GC = env["game"].initialize() 45 | 46 | model_loader = env["model_loaders"][0] 47 | model = model_loader.load_model(GC.params) 48 | 49 | mi = env['mi'] 50 | mi.add_model("model", model) 51 | mi.add_model("actor", model) 52 | mi["model"].eval() 53 | mi["actor"].eval() 54 | 55 | console = GoConsoleGTP(GC, evaluator) 56 | 57 | def human_actor(batch): 58 | return console.prompt("", batch) 59 | 60 | def actor(batch): 61 | return console.actor(batch) 62 | 63 | def train(batch): 64 | console.prompt("DF Train> ", batch) 65 | 66 | evaluator.setup(sampler=env["sampler"], mi=mi) 67 | 68 | GC.reg_callback_if_exists("actor_black", actor) 69 | GC.reg_callback_if_exists("human_actor", human_actor) 70 | GC.reg_callback_if_exists("train", train) 71 | 72 | GC.start() 73 | GC.GC.getClient().setRequest( 74 | mi["actor"].step, -1, env['game'].options.resign_thres, -1) 75 | 76 | evaluator.episode_start(0) 77 | 78 | while True: 79 | GC.run() 80 | if console.exit: 81 | break 82 | GC.stop() 83 | 84 | 85 | if __name__ == '__main__': 86 | main() 87 | -------------------------------------------------------------------------------- /scripts/elfgames/go/gtp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright (c) 2018-present, Facebook, Inc. 4 | # All rights reserved. 5 | # 6 | # This source code is licensed under the BSD-style license found in the 7 | # LICENSE file in the root directory of this source tree. 8 | 9 | MODEL=$1 10 | shift 11 | 12 | game=elfgames.go.game model=df_pred model_file=elfgames.go.df_model3 python3 df_console.py --mode online --keys_in_reply V rv \ 13 | --use_mcts --mcts_verbose_time --mcts_use_prior --mcts_persistent_tree --load $MODEL \ 14 | --server_addr localhost --port 1234 \ 15 | --replace_prefix resnet.module,resnet init_conv.module,init_conv \ 16 | --no_check_loaded_options \ 17 | --no_parameter_print \ 18 | "$@" 19 | -------------------------------------------------------------------------------- /scripts/elfgames/go/server_addrs.py: -------------------------------------------------------------------------------- 1 | addrs = { 2 | "myserver": "[XXX.XXX.XXX.XXX]", 3 | } 4 | -------------------------------------------------------------------------------- /scripts/elfgames/go/start_client.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright (c) 2018-present, Facebook, Inc. 4 | # All rights reserved. 5 | # 6 | # This source code is licensed under the BSD-style license found in the 7 | # LICENSE file in the root directory of this source tree. 8 | 9 | echo $PYTHONPATH $SLURMD_NODENAME $CUDA_VISIBLE_DEVICES 10 | 11 | root=./myserver game=elfgames.go.game model=df_pred model_file=elfgames.go.df_model3 \ 12 | stdbuf -o 0 -e 0 python ./selfplay.py \ 13 | --T 1 --batchsize 128 \ 14 | --dim0 256 --dim1 256 --gpu 0 \ 15 | --keys_in_reply V rv --mcts_alpha 0.03 \ 16 | --mcts_epsilon 0.25 --mcts_persistent_tree \ 17 | --mcts_puct 0.85 --mcts_rollout_per_thread 200 \ 18 | --mcts_threads 8 --mcts_use_prior \ 19 | --mcts_virtual_loss 5 --mode selfplay \ 20 | --num_block0 20 --num_block1 20 \ 21 | --num_games 32 --ply_pass_enabled 160 \ 22 | --policy_distri_cutoff 30 --policy_distri_training_for_all \ 23 | --port 1234 \ 24 | --no_check_loaded_options0 --no_check_loaded_options1 \ 25 | --replace_prefix0 resnet.module,resnet init_conv.module,init_conv\ 26 | --replace_prefix1 resnet.module,resnet init_conv.module,init_conv\ 27 | --resign_thres 0.0 --selfplay_timeout_usec 10 \ 28 | --server_id myserver --use_mcts \ 29 | --use_fp160 --use_fp161 \ 30 | --use_mcts_ai2 --verbose 31 | -------------------------------------------------------------------------------- /scripts/elfgames/go/start_selfplay.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright (c) 2018-present, Facebook, Inc. 4 | # All rights reserved. 5 | # 6 | # This source code is licensed under the BSD-style license found in the 7 | # LICENSE file in the root directory of this source tree. 8 | 9 | LOAD0=$1 10 | shift 11 | 12 | LOAD1=$1 13 | shift 14 | 15 | BATCHSIZE=$1 16 | shift 17 | 18 | NUM_ROLLOUTS=$1 19 | shift 20 | 21 | BATCHSIZE2=$1 22 | shift 23 | 24 | NUM_ROLLOUTS2=$1 25 | shift 26 | 27 | GPU=$1 28 | shift 29 | 30 | DIM=256 31 | NUM_BLOCK=20 32 | 33 | game=elfgames.go.game model=df_pred model_file=elfgames.go.df_model3 python3 selfplay.py \ 34 | --mode selfplay --selfplay_timeout_usec 10 \ 35 | --batchsize $BATCHSIZE --mcts_rollout_per_batch $BATCHSIZE \ 36 | --num_games 1 --keys_in_reply V rv --port 2341 --server_id myserver \ 37 | --mcts_threads 2 --mcts_rollout_per_thread $NUM_ROLLOUTS \ 38 | --use_mcts --use_mcts_ai2 --mcts_use_prior \ 39 | --mcts_persistent_tree --mcts_puct 1.5 \ 40 | --batchsize2 $BATCHSIZE2 --white_mcts_rollout_per_batch $BATCHSIZE2 \ 41 | --white_mcts_rollout_per_thread $NUM_ROLLOUTS2 \ 42 | --eval_model_pair loaded \ 43 | --policy_distri_cutoff 0 \ 44 | --mcts_virtual_loss 1 --mcts_epsilon 0.0 --mcts_alpha 0.00 \ 45 | --resign_thres 0.05 \ 46 | --num_block0 $NUM_BLOCK --dim0 $DIM \ 47 | --num_block1 $NUM_BLOCK --dim1 $DIM \ 48 | --no_check_loaded_options0 \ 49 | --no_check_loaded_options1 \ 50 | --verbose \ 51 | --gpu $GPU \ 52 | --load0 $LOAD0 \ 53 | --load1 $LOAD1 \ 54 | --use_fp160 --use_fp161 \ 55 | --gpu $GPU \ 56 | --replace_prefix0 resnet.module,resnet --replace_prefix1 resnet.module,resnet \ 57 | "$@" 58 | -------------------------------------------------------------------------------- /scripts/elfgames/go/start_server.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright (c) 2018-present, Facebook, Inc. 4 | # All rights reserved. 5 | # 6 | # This source code is licensed under the BSD-style license found in the 7 | # LICENSE file in the root directory of this source tree. 8 | 9 | save=./myserver game=elfgames.go.game model=df_kl model_file=elfgames.go.df_model3 \ 10 | stdbuf -o 0 -e 0 python -u ./train.py \ 11 | --mode train --batchsize 2048 \ 12 | --num_games 2048 --keys_in_reply V \ 13 | --T 1 --use_data_parallel \ 14 | --num_minibatch 1000 --num_episode 1000000 \ 15 | --mcts_threads 8 --mcts_rollout_per_thread 200 \ 16 | --keep_prev_selfplay --keep_prev_selfplay \ 17 | --use_mcts --use_mcts_ai2 \ 18 | --mcts_persistent_tree --mcts_use_prior \ 19 | --mcts_virtual_loss 5 --mcts_epsilon 0.25 \ 20 | --mcts_alpha 0.03 --mcts_puct 0.85 \ 21 | --resign_thres 0.01 --gpu 0 \ 22 | --server_id myserver --eval_num_games 400 \ 23 | --eval_winrate_thres 0.55 --port 1234 \ 24 | --q_min_size 200 --q_max_size 4000 \ 25 | --save_first \ 26 | --num_block 20 --dim 256 \ 27 | --weight_decay 0.0002 --opt_method sgd \ 28 | --bn_momentum=0 --num_cooldown=50 \ 29 | --expected_num_client 496 \ 30 | --selfplay_init_num 0 --selfplay_update_num 0 \ 31 | --eval_num_games 0 --selfplay_async \ 32 | --lr 0.01 --momentum 0.9 1>> log.log 2>&1 & 33 | -------------------------------------------------------------------------------- /src_cpp/elf/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.3) 2 | project(elf) 3 | 4 | # Source files 5 | 6 | set(ELF_SOURCES 7 | Pybind.cc 8 | concurrency/Counter.cc 9 | logging/IndexedLoggerFactory.cc 10 | logging/Levels.cc 11 | logging/Pybind.cc 12 | options/OptionMap.cc 13 | options/OptionSpec.cc 14 | options/Pybind.cc 15 | ) 16 | 17 | set(ELF_TEST_SOURCES 18 | options/OptionMapTest.cc 19 | options/OptionSpecTest.cc 20 | ) 21 | 22 | # Main ELF library 23 | 24 | add_library(elf ${ELF_SOURCES}) 25 | target_compile_definitions(elf PUBLIC 26 | GIT_COMMIT_HASH=${GIT_COMMIT_HASH} 27 | GIT_STAGED=${GIT_STAGED_STRING} 28 | ) 29 | 30 | target_link_libraries(elf PUBLIC 31 | #${Boost_LIBRARIES} 32 | concurrentqueue 33 | nlohmann_json 34 | pybind11 35 | $ 36 | spdlog 37 | ${TBB_IMPORTED_TARGETS} 38 | ) 39 | 40 | # Tests 41 | 42 | enable_testing() 43 | add_cpp_tests(test_cpp_elf_ elf ${ELF_TEST_SOURCES}) 44 | 45 | # Python bindings 46 | 47 | pybind11_add_module(_elf pybind_module.cc) 48 | target_link_libraries(_elf PRIVATE 49 | elf 50 | ) 51 | #set_target_properties(_elf PROPERTIES 52 | # LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}") 53 | -------------------------------------------------------------------------------- /src_cpp/elf/Pybind.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2018-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | */ 8 | 9 | #pragma once 10 | 11 | #include 12 | 13 | namespace elf { 14 | 15 | void registerPy(pybind11::module& m); 16 | 17 | } // namespace elf 18 | -------------------------------------------------------------------------------- /src_cpp/elf/ai/tree_search/tree_search_alg.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2018-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | */ 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "tree_search_base.h" 17 | 18 | namespace elf { 19 | namespace ai { 20 | namespace tree_search { 21 | 22 | template 23 | MCTSResultT MostVisited(const Map& vals) { 24 | using A = typename Map::key_type; 25 | using MCTSResult = MCTSResultT; 26 | static_assert( 27 | is_same::value, 28 | "key type must be EdgeInfo"); 29 | 30 | MCTSResult res; 31 | for (const std::pair& action_pair : vals) { 32 | const EdgeInfo& info = action_pair.second; 33 | 34 | res.feed(info.num_visits, action_pair); 35 | } 36 | return res; 37 | }; 38 | 39 | template 40 | MCTSResultT StrongestPrior(const Map& vals) { 41 | using A = typename Map::key_type; 42 | using MCTSResult = MCTSResultT; 43 | static_assert( 44 | is_same::value, 45 | "key type must be EdgeInfo"); 46 | 47 | MCTSResult res; 48 | for (const std::pair& action_pair : vals) { 49 | const EdgeInfo& info = action_pair.second; 50 | 51 | res.feed(info.prior_probability, action_pair); 52 | } 53 | return res; 54 | }; 55 | 56 | template 57 | MCTSResultT UniformRandom(const Map& vals) { 58 | using A = typename Map::key_type; 59 | using MCTSResult = MCTSResultT; 60 | static_assert( 61 | is_same::value, 62 | "key type must be EdgeInfo"); 63 | 64 | static std::mt19937 rng(time(NULL)); 65 | static std::mutex mu; 66 | 67 | MCTSResult res; 68 | 69 | int idx = 0; 70 | { 71 | std::lock_guard lock(mu); 72 | idx = rng() % vals.size(); 73 | } 74 | auto it = vals.begin(); 75 | while (--idx >= 0) { 76 | ++it; 77 | } 78 | 79 | res.feed(it->second.num_visits, *it); 80 | return res; 81 | }; 82 | 83 | } // namespace tree_search 84 | } // namespace ai 85 | } // namespace elf 86 | -------------------------------------------------------------------------------- /src_cpp/elf/base/common.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2018-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | */ 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | namespace elf { 18 | 19 | template 20 | class TypeNameT { 21 | public: 22 | static std::string name() { 23 | return "unknown"; 24 | } 25 | }; 26 | 27 | #define TYPE_NAME_CLASS(T) \ 28 | template <> \ 29 | class TypeNameT { \ 30 | public: \ 31 | static std::string name() { \ 32 | return #T; \ 33 | } \ 34 | }; 35 | 36 | TYPE_NAME_CLASS(float); 37 | TYPE_NAME_CLASS(double); 38 | TYPE_NAME_CLASS(int64_t); 39 | TYPE_NAME_CLASS(int32_t); 40 | 41 | struct Size { 42 | public: 43 | Size(std::initializer_list l) : sz_(l) {} 44 | Size(const std::vector& l) : sz_(l) {} 45 | Size(const Size& s) : sz_(s.sz_) {} 46 | Size(int s) { 47 | sz_.push_back(s); 48 | } 49 | Size() {} 50 | size_t nelement() const { 51 | int n = 1; 52 | for (const int& v : sz_) 53 | n *= v; 54 | return n; 55 | } 56 | 57 | const std::vector& vec() const { 58 | return sz_; 59 | } 60 | int operator[](int i) const { 61 | return sz_[i]; 62 | } 63 | size_t size() const { 64 | return sz_.size(); 65 | } 66 | 67 | Size getContinuousStrides(int type_size) const { 68 | // size to stride. 69 | std::vector prod(sz_.size(), 1); 70 | for (int i = sz_.size() - 1; i >= 1; --i) { 71 | prod[i - 1] = prod[i] * sz_[i]; 72 | } 73 | for (auto& v : prod) { 74 | v *= type_size; 75 | } 76 | return Size(prod); 77 | } 78 | 79 | Size divide(int k) const { 80 | std::vector res(sz_); 81 | for (int& r : res) { 82 | r /= k; 83 | } 84 | return Size(res); 85 | } 86 | 87 | size_t norder() const { 88 | return sz_.size(); 89 | } 90 | std::string info() const { 91 | std::stringstream ss; 92 | ss << "("; 93 | for (const int& v : sz_) 94 | ss << v << ","; 95 | ss << ")"; 96 | return ss.str(); 97 | } 98 | 99 | private: 100 | std::vector sz_; 101 | }; 102 | 103 | } // namespace elf 104 | -------------------------------------------------------------------------------- /src_cpp/elf/base/hist.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2018-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | */ 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | namespace elf { 17 | 18 | // Accumulate history buffer. 19 | template 20 | class HistT { 21 | public: 22 | enum MemOrder { BATCH_HIST, HIST_BATCH }; 23 | 24 | HistT(size_t q_size, size_t vec_size, MemOrder order) 25 | : vec_size_(vec_size), order_(order) { 26 | q_ = std::vector>(q_size, std::vector(vec_size_)); 27 | assert(q_.size() > 0); 28 | assert(q_[0].size() == vec_size_); 29 | } 30 | 31 | T* prepare() { 32 | q_idx_ = (q_idx_ + 1) % q_.size(); 33 | return &q_[q_idx_][0]; 34 | } 35 | 36 | void extract(T* s, int batchsize, int batch_idx) const { 37 | switch (order_) { 38 | case BATCH_HIST: 39 | ext_batch_hist(s, batch_idx); 40 | break; 41 | case HIST_BATCH: 42 | ext_hist_batch(s, batchsize, batch_idx); 43 | break; 44 | default: 45 | assert(false); 46 | } 47 | } 48 | 49 | private: 50 | std::vector> q_; 51 | size_t q_idx_ = 0; 52 | size_t vec_size_; 53 | MemOrder order_; 54 | 55 | void ext_batch_hist(T* s, int batch_idx) const { 56 | // one sample = dim per feature * time length 57 | T* start = s + batch_idx * vec_size_ * q_.size(); 58 | for (const auto& v : boost::adaptors::reverse(q_)) { 59 | assert(v.size() == vec_size_); 60 | copy(v.begin(), v.end(), start); 61 | start += v.size(); 62 | } 63 | } 64 | 65 | void ext_hist_batch(T* s, int batchsize, int batch_idx) const { 66 | T* start = s + batch_idx * vec_size_; 67 | int stride = batchsize * vec_size_; 68 | for (const auto& v : boost::adaptors::reverse(q_)) { 69 | assert(v.size() == vec_size_); 70 | copy(v.begin(), v.end(), s); 71 | start += stride; 72 | } 73 | } 74 | }; 75 | 76 | } // namespace elf 77 | -------------------------------------------------------------------------------- /src_cpp/elf/comm/primitive.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2018-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | */ 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "elf/concurrency/Counter.h" 20 | 21 | class Notif { 22 | public: 23 | Notif() : _flag(false) {} 24 | 25 | const std::atomic_bool& flag() const { 26 | return _flag; 27 | } 28 | 29 | bool get() const { 30 | return _flag.load(); 31 | } 32 | 33 | void notify() { 34 | _counter.increment(); 35 | } 36 | 37 | void set() { 38 | _flag = true; 39 | } 40 | 41 | void wait(int n, std::function f = nullptr) { 42 | _flag = true; 43 | 44 | if (f == nullptr) { 45 | _counter.waitUntilCount(n); 46 | } else { 47 | while (true) { 48 | int current_cnt = 49 | _counter.waitUntilCount(n, std::chrono::microseconds(10)); 50 | 51 | // LOG(INFO) << "current cnt = " << current_cnt 52 | // << " n = " << n << std::endl; 53 | if (current_cnt >= n) { 54 | break; 55 | } 56 | f(); 57 | } 58 | } 59 | } 60 | 61 | void reset() { 62 | _counter.reset(); 63 | _flag = false; 64 | } 65 | 66 | private: 67 | std::atomic_bool _flag; // flag to indicate stop 68 | elf::concurrency::Counter _counter; 69 | }; 70 | -------------------------------------------------------------------------------- /src_cpp/elf/concurrency/Counter.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2018-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | */ 8 | 9 | #include "Counter.h" 10 | 11 | namespace elf { 12 | namespace concurrency { 13 | 14 | // Explicit instantiations for various integer types. 15 | template class Counter; 16 | template class Counter; 17 | template class Counter; 18 | 19 | } // namespace concurrency 20 | } // namespace elf 21 | -------------------------------------------------------------------------------- /src_cpp/elf/concurrency/TBBHashers.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2018-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | */ 8 | 9 | /** 10 | * Definition of various custom TBB hashers. 11 | * 12 | * TODO(maj): This is not particularly good practice, the maps requiring custom 13 | * hashers should themselves be parameterized. 14 | */ 15 | 16 | #pragma once 17 | 18 | #include 19 | 20 | #include 21 | #include 22 | 23 | #include 24 | 25 | namespace tbb { 26 | namespace interface5 { 27 | 28 | template <> 29 | inline size_t tbb_hasher(const std::thread::id& id) { 30 | return std::hash()(id); 31 | } 32 | 33 | template <> 34 | inline size_t tbb_hasher(const std::type_index& idx) { 35 | return std::hash()(idx); 36 | } 37 | 38 | } // namespace interface5 39 | } // namespace tbb 40 | -------------------------------------------------------------------------------- /src_cpp/elf/distributed/shared_replay_buffer.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2018-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | template 16 | class SharedReplayBuffer { 17 | public: 18 | using GenFunc = std::function(const Key&)>; 19 | 20 | SharedReplayBuffer(GenFunc gen) : _gen(gen) {} 21 | void InitRecords(const std::vector& keys) { 22 | std::lock_guard lock(_mutex); 23 | for (const auto& key : keys) 24 | add_record_no_lock(key); 25 | } 26 | 27 | bool HasKey(const Key& key) const { 28 | return _buffer.find(key) != _buffer.end(); 29 | } 30 | 31 | const Record& Get(const Key& key) { 32 | typename BufferType::const_iterator it = _buffer.find(key); 33 | if (it == _buffer.end()) { 34 | std::lock_guard lock(_mutex); 35 | // Check again. 36 | it = _buffer.find(key); 37 | if (it == _buffer.end()) 38 | it = add_record_no_lock(key); 39 | } 40 | return *it->second; 41 | } 42 | 43 | private: 44 | using BufferType = std::map>; 45 | 46 | BufferType _buffer; 47 | std::mutex _mutex; 48 | GenFunc _gen; 49 | 50 | typename BufferType::const_iterator add_record_no_lock(const Key& key) { 51 | assert(_gen != nullptr); 52 | return _buffer.emplace(make_pair(key, _gen(key))).first; 53 | } 54 | }; 55 | -------------------------------------------------------------------------------- /src_cpp/elf/legacy/python_options_utils_cpp.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2018-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | */ 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include "elf/ai/tree_search/tree_search_options.h" 16 | #include "elf/logging/IndexedLoggerFactory.h" 17 | #include "pybind_helper.h" 18 | 19 | struct ContextOptions { 20 | // How many simulation threads we are running. 21 | int num_games = 1; 22 | 23 | int batchsize = 0; 24 | 25 | // History length. How long we should keep the history. 26 | int T = 1; 27 | 28 | std::string job_id; 29 | 30 | elf::ai::tree_search::TSOptions mcts_options; 31 | 32 | std::shared_ptr _logger; 33 | 34 | ContextOptions() 35 | : _logger(elf::logging::getIndexedLogger( 36 | "elf::legacy::ContextOptions-", 37 | "")) {} 38 | 39 | void print() const { 40 | _logger->info("JobId: {}", job_id); 41 | _logger->info("#Game: {}", num_games); 42 | _logger->info("T: {}", T); 43 | _logger->info("{}", mcts_options.info()); 44 | } 45 | 46 | REGISTER_PYBIND_FIELDS(job_id, batchsize, num_games, T, mcts_options); 47 | }; 48 | -------------------------------------------------------------------------------- /src_cpp/elf/logging/IndexedLoggerFactory.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2018-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "IndexedLoggerFactory.h" 14 | 15 | #include 16 | 17 | namespace elf { 18 | namespace logging { 19 | 20 | void IndexedLoggerFactory::registerPy(pybind11::module& m) { 21 | namespace py = pybind11; 22 | 23 | py::class_(m, "IndexedLoggerFactory") 24 | .def(py::init()) 25 | .def(py::init()) 26 | .def("makeLogger", &IndexedLoggerFactory::makeLogger); 27 | 28 | m.def("getIndexedLogger", getIndexedLogger); 29 | } 30 | 31 | std::shared_ptr IndexedLoggerFactory::makeLogger( 32 | const std::string& prefix, 33 | const std::string& suffix) { 34 | size_t curCount = counter_++; 35 | std::string loggerName = prefix + std::to_string(curCount) + suffix; 36 | 37 | return creator_(loggerName); 38 | } 39 | 40 | std::shared_ptr getIndexedLogger( 41 | const std::string& prefix, 42 | const std::string& suffix) { 43 | static IndexedLoggerFactory factory([](const std::string& name) { 44 | auto ptr = spdlog::stderr_color_mt(name); 45 | spdlog::drop(name); 46 | return ptr; 47 | }); 48 | return factory.makeLogger(prefix, suffix); 49 | } 50 | 51 | } // namespace logging 52 | } // namespace elf 53 | -------------------------------------------------------------------------------- /src_cpp/elf/logging/IndexedLoggerFactory.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2018-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | */ 8 | 9 | /** 10 | * IndexedLoggerFactory is a class to create multiple spdlog::loggers, each 11 | * indexed by a strictly increasing counter. 12 | * 13 | * The typical usecase is when you want to associate one logger per class 14 | * instance. In this case, you'd do something like: 15 | * 16 | * namespace A { 17 | * 18 | * class B { 19 | * public: 20 | * B(std::string description) 21 | * : logger_(getLoggerFactory()->makeLogger("A::B-", "-" + description)), 22 | * description_(description) {} 23 | * 24 | * private: 25 | * static IndexedLoggerFactory* getLoggerFactory() { 26 | * static IndexedLoggerFactory factory([](const std::string& name) { 27 | * return spdlog::stderr_color_mt(name); 28 | * }); 29 | * return &factory; 30 | * } 31 | * 32 | * std::shared_ptr logger_; 33 | * std::string description_; 34 | * }; 35 | * 36 | * } 37 | * 38 | * WARNING: Use this *only* when you are able to guarantee a bounded number of 39 | * object instantiations. This class will automatically enforce an upper bound 40 | * of a few thousand. 41 | */ 42 | 43 | #pragma once 44 | 45 | #include 46 | 47 | #include 48 | #include 49 | #include 50 | #include 51 | 52 | #include 53 | 54 | namespace elf { 55 | namespace logging { 56 | 57 | class IndexedLoggerFactory { 58 | public: 59 | using CreatorT = 60 | std::function(const std::string& name)>; 61 | 62 | static void registerPy(pybind11::module& m); 63 | 64 | IndexedLoggerFactory(CreatorT creator, size_t initIndex = 0) 65 | : creator_(std::move(creator)), counter_(initIndex) {} 66 | 67 | std::shared_ptr makeLogger( 68 | const std::string& prefix, 69 | const std::string& suffix); 70 | 71 | private: 72 | CreatorT creator_; 73 | std::atomic_size_t counter_; 74 | }; 75 | 76 | std::shared_ptr getIndexedLogger( 77 | const std::string& prefix, 78 | const std::string& suffix); 79 | 80 | } // namespace logging 81 | } // namespace elf 82 | -------------------------------------------------------------------------------- /src_cpp/elf/logging/Levels.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2018-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | #include "Levels.h" 13 | 14 | #include 15 | 16 | namespace elf { 17 | namespace logging { 18 | 19 | void Levels::registerPy(pybind11::module& m) { 20 | namespace py = pybind11; 21 | using spdlog::level::level_enum; 22 | 23 | py::enum_(m, "LoggerLevel") 24 | .value("trace", level_enum::trace) 25 | .value("debug", level_enum::debug) 26 | .value("info", level_enum::info) 27 | .value("warn", level_enum::warn) 28 | .value("err", level_enum::err) 29 | .value("critical", level_enum::critical) 30 | .value("off", level_enum::off) 31 | .value("invalid", static_cast(Levels::INVALID)) 32 | .def_static( 33 | "from_str", 34 | static_cast(&Levels::from_str)); 35 | } 36 | 37 | spdlog::level::level_enum Levels::from_str(const char* str) { 38 | using spdlog::level::level_names; 39 | constexpr size_t num_levels = sizeof(level_names) / sizeof(level_names[0]); 40 | const char** begin = level_names; 41 | const char** end = level_names + num_levels; 42 | const char** iter = std::find_if(begin, end, [=](const char* level_name) { 43 | return strcmp(level_name, str) == 0; 44 | }); 45 | if (iter == end) { 46 | return static_cast(INVALID); 47 | } 48 | return static_cast(iter - begin); 49 | } 50 | 51 | } // namespace logging 52 | } // namespace elf 53 | -------------------------------------------------------------------------------- /src_cpp/elf/logging/Levels.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2018-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | */ 8 | 9 | #pragma once 10 | 11 | #include 12 | 13 | #include 14 | 15 | #include 16 | 17 | namespace elf { 18 | namespace logging { 19 | 20 | class Levels { 21 | public: 22 | static constexpr int INVALID = 127; // hack, but guaranteed to fit any enum 23 | 24 | static void registerPy(pybind11::module& m); 25 | 26 | static spdlog::level::level_enum from_str(const char* str); 27 | 28 | static spdlog::level::level_enum from_str(const std::string& str) { 29 | return from_str(str.c_str()); 30 | } 31 | }; 32 | 33 | } // namespace logging 34 | } // namespace elf 35 | -------------------------------------------------------------------------------- /src_cpp/elf/logging/Pybind.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2018-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | #include "Pybind.h" 13 | 14 | #include "IndexedLoggerFactory.h" 15 | #include "Levels.h" 16 | 17 | namespace elf { 18 | namespace logging { 19 | 20 | void registerPy(pybind11::module& m) { 21 | namespace py = pybind11; 22 | using spdlog::logger; 23 | 24 | IndexedLoggerFactory::registerPy(m); 25 | Levels::registerPy(m); 26 | 27 | /* clang-format off*/ 28 | // disable formatting due to macros 29 | 30 | // This macro defines a logging function for the given loglevel in Pythonland. 31 | #define _ELF_PYBIND_DECLARE_LOG_LEVEL(level) \ 32 | .def( \ 33 | #level, \ 34 | static_cast( \ 35 | &logger::level)) 36 | 37 | py::class_>(m, "Logger") 38 | _ELF_PYBIND_DECLARE_LOG_LEVEL(trace) _ELF_PYBIND_DECLARE_LOG_LEVEL(debug) 39 | _ELF_PYBIND_DECLARE_LOG_LEVEL(info) 40 | _ELF_PYBIND_DECLARE_LOG_LEVEL(warn) 41 | _ELF_PYBIND_DECLARE_LOG_LEVEL(error) 42 | _ELF_PYBIND_DECLARE_LOG_LEVEL(critical) 43 | .def("flush", &logger::flush) 44 | .def("flush_on", &logger::flush_on) 45 | .def("level", &logger::level) 46 | .def("name", &logger::name) 47 | .def("set_formatter", &logger::set_formatter) 48 | .def("set_level", &logger::set_level) 49 | .def("should_log", &logger::should_log); 50 | 51 | #undef _ELF_PYBIND_DECLARE_LOG_LEVEL 52 | 53 | m.def("drop", spdlog::drop) 54 | .def("drop_all", spdlog::drop_all) 55 | .def("get", spdlog::get) 56 | .def("set_level", spdlog::set_level) 57 | .def("set_pattern", spdlog::set_pattern) 58 | .def("daily_logger_mt", spdlog::daily_logger_mt) 59 | .def("rotating_logger_mt", spdlog::rotating_logger_mt) 60 | .def("stdout_logger_mt", spdlog::stdout_logger_mt) 61 | .def("stderr_logger_mt", spdlog::stderr_logger_mt) 62 | .def("stdout_color_mt", spdlog::stdout_color_mt) 63 | .def("stderr_color_mt", spdlog::stderr_color_mt); 64 | /* clang-format on */ 65 | } 66 | 67 | } // namespace logging 68 | } // namespace elf 69 | -------------------------------------------------------------------------------- /src_cpp/elf/logging/Pybind.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2018-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | */ 8 | 9 | #pragma once 10 | 11 | #include 12 | 13 | namespace elf { 14 | namespace logging { 15 | 16 | void registerPy(pybind11::module& m); 17 | 18 | } // namespace logging 19 | } // namespace elf 20 | -------------------------------------------------------------------------------- /src_cpp/elf/options/OptionMap.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2018-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | #include "OptionMap.h" 13 | 14 | #include 15 | 16 | using nlohmann::json; 17 | 18 | namespace elf { 19 | namespace options { 20 | 21 | void OptionMap::registerPy(pybind11::module& m) { 22 | namespace py = pybind11; 23 | 24 | py::class_(m, "OptionMap") 25 | .def(py::init()) 26 | .def(py::init()) 27 | .def("getOptionSpec", &OptionMap::getOptionSpec) 28 | .def("getJSONString", &OptionMap::getJSONString) 29 | .def("loadJSONString", &OptionMap::loadJSONString) 30 | .def("getAsJSONString", &OptionMap::getAsJSONString) 31 | .def("setAsJSONString", &OptionMap::setAsJSONString); 32 | } 33 | 34 | void OptionMap::loadJSON(const json& data) { 35 | for (auto it = data.begin(); it != data.end(); ++it) { 36 | data_[it.key()] = it.value(); 37 | } 38 | } 39 | 40 | const json& OptionMap::getAsJSON(const std::string& optionName) const { 41 | const auto& elem = data_.find(optionName); 42 | if (elem == data_.end()) { 43 | throw std::runtime_error(optionName + " has not been set!"); 44 | } 45 | return elem.value(); 46 | } 47 | 48 | } // namespace options 49 | } // namespace elf 50 | -------------------------------------------------------------------------------- /src_cpp/elf/options/OptionSpecTest.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2018-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | */ 8 | 9 | #include "OptionSpec.h" 10 | 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | namespace elf { 17 | namespace options { 18 | 19 | class OptionSpecTest : public ::testing::Test { 20 | protected: 21 | virtual void SetUp() { 22 | spec1_.addOption("some_int", "some_int help"); 23 | spec1_.addOption("some_str", "some_str help", "a default"); 24 | spec1_.addOption>( 25 | "some_floats", "some_floats help", {1.23, 4.56}); 26 | spec2_.addOption("some_bool", "some_bool help", false); 27 | spec2_.addOption("some_other_bool", "some_other_bool help", true); 28 | mergedSpec_ = spec1_; 29 | mergedSpec_.merge(spec2_); 30 | } 31 | 32 | OptionSpec spec1_, spec2_, mergedSpec_; 33 | }; 34 | 35 | } // namespace options 36 | } // namespace elf 37 | -------------------------------------------------------------------------------- /src_cpp/elf/options/Pybind.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2018-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | #include "Pybind.h" 13 | 14 | #include "OptionMap.h" 15 | #include "OptionSpec.h" 16 | 17 | namespace elf { 18 | namespace options { 19 | 20 | void registerPy(pybind11::module& m) { 21 | namespace py = pybind11; 22 | 23 | OptionMap::registerPy(m); 24 | OptionSpec::registerPy(m); 25 | } 26 | 27 | } // namespace options 28 | } // namespace elf 29 | -------------------------------------------------------------------------------- /src_cpp/elf/options/Pybind.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2018-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | */ 8 | 9 | #pragma once 10 | 11 | #include 12 | 13 | namespace elf { 14 | namespace options { 15 | 16 | void registerPy(pybind11::module& m); 17 | 18 | } // namespace options 19 | } // namespace elf 20 | -------------------------------------------------------------------------------- /src_cpp/elf/pybind_module.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2018-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | */ 8 | 9 | #include 10 | 11 | #include "Pybind.h" 12 | 13 | PYBIND11_MODULE(_elf, m) { 14 | elf::registerPy(m); 15 | } 16 | -------------------------------------------------------------------------------- /src_cpp/elf/utils/json_utils.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2018-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | */ 8 | 9 | #pragma once 10 | 11 | #define JSON_LOAD(target, j, field) \ 12 | if (j.find(#field) != j.end()) { \ 13 | target.field = j[#field]; \ 14 | } else { \ 15 | throw std::runtime_error(#field "cannot not be found!"); \ 16 | } 17 | 18 | #define JSON_LOAD_OPTIONAL(target, j, field) \ 19 | if (j.find(#field) != j.end()) { \ 20 | target.field = j[#field]; \ 21 | } 22 | 23 | #define JSON_SAVE(j, field) j[#field] = field; 24 | 25 | #define JSON_SAVE_OBJ(j, field) field.setJsonFields(j[#field]); 26 | 27 | #define JSON_LOAD_OBJ(target, j, field) \ 28 | if (j.find(#field) != j.end()) { \ 29 | target.field = target.field.createFromJson(j[#field]); \ 30 | } else { \ 31 | throw std::runtime_error(#field "cannot not be found!"); \ 32 | } 33 | 34 | #define JSON_LOAD_OBJ_ARGS(target, j, field, ...) \ 35 | if (j.find(#field) != j.end()) { \ 36 | target.field = target.field.createFromJson(j[#field], __VA_ARGS__); \ 37 | } else { \ 38 | throw std::runtime_error(#field "cannot not be found!"); \ 39 | } 40 | 41 | #define JSON_LOAD_VEC(target, j, field) \ 42 | target.field.clear(); \ 43 | if (j.find(#field) != j.end()) { \ 44 | for (size_t i = 0; i < j[#field].size(); ++i) { \ 45 | target.field.push_back(j[#field][i]); \ 46 | } \ 47 | } else { \ 48 | throw std::runtime_error(#field "cannot not be found!"); \ 49 | } 50 | 51 | #define JSON_LOAD_VEC_OPTIONAL(target, j, field) \ 52 | target.field.clear(); \ 53 | if (j.find(#field) != j.end()) { \ 54 | for (size_t i = 0; i < j[#field].size(); ++i) { \ 55 | target.field.push_back(j[#field][i]); \ 56 | } \ 57 | } 58 | -------------------------------------------------------------------------------- /src_cpp/elf/utils/member_check.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2018-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | */ 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | 14 | #define MEMBER_CHECK(member) \ 15 | \ 16 | template \ 17 | struct has_##member : std::false_type {}; \ 18 | \ 19 | template \ 20 | struct has_##member<__T, decltype((void)__T::member, 0)> : std::true_type { \ 21 | }; 22 | 23 | #define MEMBER_FUNC_CHECK(func) \ 24 | template \ 25 | struct has_func_##func { \ 26 | template \ 27 | static char test(decltype(&__C::func)); \ 28 | template \ 29 | static long test(...); \ 30 | enum { value = sizeof(test<__T>(0)) == sizeof(char) }; \ 31 | }; 32 | -------------------------------------------------------------------------------- /src_cpp/elfgames/go/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED(VERSION 3.3) 2 | project(elfgames_go) 3 | 4 | # Source files 5 | 6 | set(ELFGAMES_GO_SOURCES 7 | base/board_feature.cc 8 | base/common.cc 9 | base/go_state.cc 10 | base/board.cc 11 | sgf/sgf.cc 12 | common/game_selfplay.cc 13 | common/go_state_ext.cc 14 | train/client_manager.cc 15 | train/game_train.cc 16 | train/Pybind.cc 17 | ) 18 | 19 | set(ELFGAMES_GO_INFERENCE_SOURCES 20 | base/board_feature.cc 21 | base/common.cc 22 | base/go_state.cc 23 | base/board.cc 24 | sgf/sgf.cc 25 | common/game_selfplay.cc 26 | common/go_state_ext.cc 27 | inference/Pybind.cc 28 | ) 29 | 30 | # Main Go library 31 | 32 | add_library(elfgames_go ${ELFGAMES_GO_SOURCES}) 33 | if(${BOARD9x9}) 34 | message("Use 9x9 board") 35 | target_compile_definitions(elfgames_go PUBLIC BOARD9x9) 36 | endif() 37 | target_link_libraries(elfgames_go PUBLIC 38 | cppzmq 39 | elf 40 | ) 41 | 42 | add_library(elfgames_go_inference ${ELFGAMES_GO_INFERENCE_SOURCES}) 43 | if(${BOARD9x9}) 44 | message("Use 9x9 board") 45 | target_compile_definitions(elfgames_go_inference PUBLIC BOARD9x9) 46 | endif() 47 | target_link_libraries(elfgames_go_inference PUBLIC 48 | elf 49 | ) 50 | 51 | # For unit-test purpose, build 9x9 library 52 | add_library(elfgames_go9 ${ELFGAMES_GO_SOURCES}) 53 | target_compile_definitions(elfgames_go9 PUBLIC BOARD9x9) 54 | target_link_libraries(elfgames_go9 PUBLIC 55 | cppzmq 56 | elf 57 | ) 58 | 59 | # Python bindings 60 | 61 | pybind11_add_module(_elfgames_go train/pybind_module.cc) 62 | target_link_libraries(_elfgames_go PRIVATE 63 | elfgames_go 64 | zmq 65 | ) 66 | 67 | 68 | pybind11_add_module(_elfgames_go_inference inference/pybind_module.cc) 69 | target_link_libraries(_elfgames_go_inference PRIVATE 70 | elfgames_go_inference 71 | ) 72 | 73 | #set_target_properties(_elfgames_go PROPERTIES 74 | # LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}") 75 | 76 | # unit-test here: 77 | set(GO_TEST_SOURCES 78 | base/test/coord_test.cc 79 | base/test/go_test.cc 80 | base/test/board_feature_test.cc 81 | base/test/symmetry_test.cc 82 | sgf/sgf_test.cc 83 | #mcts/mcts_test.cc 84 | ) 85 | enable_testing() 86 | add_cpp_tests(test_cpp_elfgames_go_ elfgames_go9 ${GO_TEST_SOURCES}) 87 | -------------------------------------------------------------------------------- /src_cpp/elfgames/go/base/common.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2018-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | */ 8 | 9 | #include "common.h" 10 | #include 11 | #include 12 | 13 | double __attribute__((noinline)) wallclock(void) { 14 | struct timeval t; 15 | gettimeofday(&t, NULL); 16 | return (1.0e-6 * t.tv_usec + t.tv_sec); 17 | } 18 | 19 | uint64_t __attribute__((noinline)) wallclock64() { 20 | return (uint64_t)(wallclock() * 1e6); 21 | } 22 | 23 | void dbg_printf(const char* format, ...) { 24 | (void)(format); 25 | #ifdef DEBUG 26 | va_list argptr; 27 | va_start(argptr, format); 28 | printf("INFO: "); 29 | vprintf(format, argptr); 30 | va_end(argptr); 31 | printf("\n"); 32 | fflush(stdout); 33 | #endif 34 | } 35 | 36 | void error(const char* format, ...) { 37 | va_list argptr; 38 | va_start(argptr, format); 39 | printf("ERROR: "); 40 | vprintf(format, argptr); 41 | va_end(argptr); 42 | printf("\n"); 43 | fflush(stdout); 44 | // Make an easy sev. 45 | char* a = NULL; 46 | *a = 1; 47 | exit(1); 48 | } 49 | -------------------------------------------------------------------------------- /src_cpp/elfgames/go/base/common.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2018-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | */ 8 | 9 | #ifndef _COMMON_H_ 10 | #define _COMMON_H_ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | double __attribute__((noinline)) wallclock(void); 22 | uint64_t __attribute__((noinline)) wallclock64(); 23 | 24 | void dbg_printf(const char* format, ...); 25 | void error(const char* format, ...); 26 | 27 | #ifdef __cplusplus 28 | } 29 | #endif 30 | 31 | #define __STR_EXPAND(tok) #tok 32 | #define __STR(tok) __STR_EXPAND(tok) 33 | 34 | typedef unsigned short Coord; 35 | typedef unsigned char Stone; 36 | 37 | #define S_EMPTY 0 38 | #define S_BLACK 1 39 | #define S_WHITE 2 40 | #define S_OFF_BOARD 3 41 | 42 | // Two special moves. 43 | #define M_PASS 0 // (-1, -1) 44 | #define M_RESIGN 1 // (0, -1) 45 | // Used when we want to skip and let the opponent play. 46 | #define M_SKIP 2 47 | #define M_INVALID 3 48 | #define M_CLEAR 4 49 | 50 | #define STR_BOOL(s) ((s) ? "true" : "false") 51 | #define STR_STONE(s) ((s) == S_BLACK ? "B" : ((s) == S_WHITE ? "W" : "U")) 52 | 53 | #define timeit \ 54 | { \ 55 | double __start = wallclock(); 56 | 57 | #define endtime \ 58 | double __duration = wallclock() - __start; \ 59 | printf("Time spent = %lf\n", __duration); \ 60 | } 61 | 62 | #define endtime2(t) \ 63 | t = wallclock() - __start; \ 64 | } 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /src_cpp/elfgames/go/base/go_common.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2018-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | */ 8 | 9 | #include "board.h" 10 | 11 | constexpr uint64_t BOARD_ACTION_PASS = BOARD_SIZE * BOARD_SIZE; 12 | constexpr uint64_t BOARD_NUM_ACTION = BOARD_SIZE * BOARD_SIZE + 1; 13 | 14 | // Maximum move. 15 | constexpr int BOARD_MAX_MOVE = BOARD_SIZE * BOARD_SIZE * 2; 16 | -------------------------------------------------------------------------------- /src_cpp/elfgames/go/base/test/coord_test.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2018-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | */ 8 | 9 | /** 10 | * Acknowledgement: 11 | * These tests are loosely ported from the MiniGo project's excellent unit 12 | * tests. https://github.com/tensorflow/minigo 13 | */ 14 | 15 | #include 16 | 17 | #include "elfgames/go/base/go_state.h" 18 | #include "elfgames/go/sgf/sgf.h" 19 | 20 | // All tests assumes BOARD_SIZE = 9 21 | // We use padding=1, so actually BOARD_EXPAND_SIZE = 11 22 | // For a coordinate (x, y) 23 | // flatten is (x+1) + (y+1)*BOARD_EXPAND_SIZE 24 | TEST(CoordTest, testUpperLeft) { 25 | // We use the pygtp system for coordinates 26 | Coord c = str2coord("aa"); 27 | EXPECT_EQ(c, 12); 28 | std::string str = coord2str(c); 29 | 30 | // TEST: aa -> c -> aa 31 | EXPECT_EQ(str, "aa"); 32 | int x = X(c); 33 | int y = Y(c); 34 | EXPECT_EQ(x, 0); 35 | EXPECT_EQ(y, 0); 36 | } 37 | 38 | TEST(CoordTest, testTopLeft) { 39 | // We use the pygtp system for coordinates 40 | Coord c = str2coord("ia"); 41 | EXPECT_EQ(c, 20); 42 | std::string str = coord2str(c); 43 | 44 | // TEST: ia -> c -> ia 45 | EXPECT_EQ(str, "ia"); 46 | int x = X(c); 47 | int y = Y(c); 48 | EXPECT_EQ(x, 8); 49 | EXPECT_EQ(y, 0); 50 | } 51 | 52 | TEST(CoordTest, testPass) { 53 | Coord c = str2coord(""); 54 | EXPECT_EQ(c, 0); 55 | std::string str = coord2str(c); 56 | EXPECT_EQ(str, ""); 57 | } 58 | 59 | TEST(CoordTest, testParse9x9) { 60 | int x, y; 61 | Coord c; 62 | std::string str; 63 | 64 | c = str2coord("aa"); 65 | x = X(c); 66 | y = Y(c); 67 | EXPECT_EQ(x, 0); 68 | EXPECT_EQ(y, 0); 69 | 70 | c = str2coord("ac"); 71 | x = X(c); 72 | y = Y(c); 73 | EXPECT_EQ(x, 0); 74 | EXPECT_EQ(y, 2); 75 | 76 | c = str2coord("ca"); 77 | x = X(c); 78 | y = Y(c); 79 | EXPECT_EQ(x, 2); 80 | EXPECT_EQ(y, 0); 81 | 82 | str = coord2str(str2coord("aa")); 83 | EXPECT_EQ(str, "aa"); 84 | 85 | str = coord2str(str2coord("ha")); 86 | EXPECT_EQ(str, "ha"); 87 | } 88 | 89 | int main(int argc, char** argv) { 90 | testing::InitGoogleTest(&argc, argv); 91 | 92 | return RUN_ALL_TESTS(); 93 | } 94 | -------------------------------------------------------------------------------- /src_cpp/elfgames/go/base/test/test_utils.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2018-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | */ 8 | 9 | #include "elfgames/go/base/board.h" 10 | #include "elfgames/go/base/common.h" 11 | #include "elfgames/go/base/go_state.h" 12 | 13 | Coord toFlat(const int x, const int y) { 14 | Coord c; 15 | c = (y + 1) * BOARD_EXPAND_SIZE + x + 1; 16 | return c; 17 | } 18 | 19 | // revert colors in a string representing a board 20 | void flipColors(std::string& s) { 21 | for (size_t i = 0; i < s.size(); ++i) { 22 | if (s[i] == 'X') 23 | s[i] = 'O'; 24 | else if (s[i] == 'O') 25 | s[i] = 'X'; 26 | } 27 | } 28 | 29 | Stone getTurn(const GoState& b) { 30 | if (b.getPly() % 2 == 0) 31 | return S_WHITE; 32 | else if (b.getPly() % 2 == 1) 33 | return S_BLACK; 34 | else 35 | throw "Unknown player"; 36 | } 37 | 38 | void giveTurn(GoState& b, const Stone s) { 39 | if (s == S_BLACK) { 40 | if (getTurn(b) == S_WHITE) 41 | b.forward(0); 42 | } else if (s == S_WHITE) { 43 | if (getTurn(b) == S_BLACK) 44 | b.forward(0); 45 | } else 46 | throw "Unknown player"; 47 | } 48 | 49 | void loadBoard(GoState& b, const std::string& str) { 50 | assert(str.size() == BOARD_SIZE * BOARD_SIZE); 51 | int x, y; 52 | Coord c; 53 | for (int i = 0; i < BOARD_SIZE * BOARD_SIZE; ++i) { 54 | assert(str[i] == '.' || str[i] == 'X' || str[i] == 'O'); 55 | 56 | x = i % BOARD_SIZE; 57 | y = i / BOARD_SIZE; 58 | c = toFlat(x, y); 59 | if (str[i] == '.') 60 | continue; 61 | else { 62 | // make one pass if not the player to play 63 | if ((str[i] == 'X' && getTurn(b) == S_WHITE) || 64 | (str[i] == 'O' && getTurn(b) == S_BLACK)) 65 | b.forward(0); 66 | b.forward(c); 67 | } 68 | } 69 | } 70 | 71 | bool boardEqual(const GoState& b1, const GoState& b2) { 72 | for (int j = 0; j < BOARD_SIZE; ++j) { // y 73 | for (int i = 0; i < BOARD_SIZE; ++i) { // x 74 | Coord c = toFlat(i, j); 75 | if (b1.board()._infos[c].color != b2.board()._infos[c].color) { 76 | return false; 77 | } 78 | } 79 | } 80 | return true; 81 | } 82 | 83 | // add all the coords with the specified group id 84 | // to set s 85 | void addSet(const GoState& b, const unsigned char id, std::set& s) { 86 | Coord c = b.board()._groups[id].start; 87 | 88 | while (s.find(c) == s.end()) { 89 | s.insert(c); 90 | // c move to next 91 | c = b.board()._infos[c].next; 92 | if (c == 0) 93 | break; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src_cpp/elfgames/go/common/game_base.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2018-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | */ 8 | 9 | #pragma once 10 | 11 | #include "elf/base/context.h" 12 | #include "elf/legacy/python_options_utils_cpp.h" 13 | #include "elf/logging/IndexedLoggerFactory.h" 14 | #include "elf/utils/utils.h" 15 | 16 | #include "game_feature.h" 17 | 18 | class GoGameBase { 19 | public: 20 | GoGameBase( 21 | int game_idx, 22 | elf::GameClient* client, 23 | const ContextOptions& context_options, 24 | const GameOptions& options) 25 | : client_(client), 26 | _game_idx(game_idx), 27 | _options(options), 28 | _context_options(context_options), 29 | _logger(elf::logging::getIndexedLogger( 30 | "elfgames::go::common::GoGameBase-", 31 | "")) { 32 | if (options.seed == 0) { 33 | _seed = elf_utils::get_seed( 34 | game_idx ^ std::hash{}(context_options.job_id)); 35 | } else { 36 | _seed = options.seed; 37 | } 38 | _rng.seed(_seed); 39 | } 40 | 41 | void mainLoop() { 42 | if (_options.verbose) { 43 | _logger->info( 44 | "[{}] Seed: {}, thread_id: {}", 45 | _game_idx, 46 | _seed, 47 | std::hash{}(std::this_thread::get_id())); 48 | } 49 | // Main loop of the game. 50 | while (!client_->DoStopGames()) { 51 | act(); 52 | } 53 | } 54 | 55 | virtual void act() = 0; 56 | 57 | virtual ~GoGameBase() = default; 58 | 59 | protected: 60 | elf::GameClient* client_ = nullptr; 61 | uint64_t _seed = 0; 62 | std::mt19937 _rng; 63 | 64 | int _game_idx = -1; 65 | 66 | GameOptions _options; 67 | ContextOptions _context_options; 68 | 69 | private: 70 | std::shared_ptr _logger; 71 | }; 72 | -------------------------------------------------------------------------------- /src_cpp/elfgames/go/common/game_selfplay.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2018-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | */ 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | #include "elf/base/dispatcher.h" 16 | #include "elf/legacy/python_options_utils_cpp.h" 17 | #include "elf/logging/IndexedLoggerFactory.h" 18 | 19 | #include "../mcts/mcts.h" 20 | #include "../sgf/sgf.h" 21 | #include "game_base.h" 22 | #include "game_feature.h" 23 | #include "game_stats.h" 24 | #include "notifier.h" 25 | 26 | // Game interface for Go. 27 | class GoGameSelfPlay : public GoGameBase { 28 | public: 29 | using ThreadedDispatcher = elf::ThreadedDispatcherT; 30 | GoGameSelfPlay( 31 | int game_idx, 32 | elf::GameClient* client, 33 | const ContextOptions& context_options, 34 | const GameOptions& options, 35 | ThreadedDispatcher* dispatcher, 36 | GameNotifierBase* notifier = nullptr); 37 | 38 | void act() override; 39 | bool OnReceive(const MsgRequest& request, RestartReply* reply); 40 | 41 | std::string showBoard() const { 42 | return _state_ext.state().showBoard(); 43 | } 44 | std::string getNextPlayer() const { 45 | return player2str(_state_ext.state().nextPlayer()); 46 | } 47 | std::string getLastMove() const { 48 | return coord2str2(_state_ext.lastMove()); 49 | } 50 | float getScore() { 51 | return _state_ext.state().evaluate(_options.komi); 52 | } 53 | 54 | float getLastScore() const { 55 | return _state_ext.getLastGameFinalValue(); 56 | } 57 | 58 | private: 59 | void setAsync(); 60 | void restart(); 61 | 62 | MCTSGoAI* init_ai( 63 | const std::string& actor_name, 64 | const elf::ai::tree_search::TSOptions& mcts_opt, 65 | float second_puct, 66 | int second_mcts_rollout_per_batch, 67 | int second_mcts_rollout_per_thread, 68 | int64_t model_ver); 69 | Coord mcts_make_diverse_move(MCTSGoAI* curr_ai, Coord c); 70 | Coord mcts_update_info(MCTSGoAI* mcts_go_ai, Coord c); 71 | void finish_game(FinishReason reason); 72 | 73 | private: 74 | ThreadedDispatcher* dispatcher_ = nullptr; 75 | GameNotifierBase* notifier_ = nullptr; 76 | GoStateExt _state_ext; 77 | 78 | Sgf _preload_sgf; 79 | Sgf::iterator _sgf_iter; 80 | 81 | int _online_counter = 0; 82 | 83 | std::unique_ptr _ai; 84 | // Opponent ai (used for selfplay evaluation) 85 | std::unique_ptr _ai2; 86 | std::unique_ptr _human_player; 87 | 88 | std::shared_ptr logger_; 89 | }; 90 | -------------------------------------------------------------------------------- /src_cpp/elfgames/go/common/game_stats.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2018-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | */ 8 | 9 | #pragma once 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "elf/logging/IndexedLoggerFactory.h" 19 | #include "game_utils.h" 20 | 21 | class GameStats { 22 | public: 23 | GameStats() 24 | : _logger(elf::logging::getIndexedLogger( 25 | "elfgames::go::common::GameStats-", 26 | "")) {} 27 | 28 | void feedMoveRanking(int ranking) { 29 | std::lock_guard lock(_mutex); 30 | _move_ranking.feed(ranking); 31 | } 32 | 33 | void resetRankingIfNeeded(int num_reset_ranking) { 34 | std::lock_guard lock(_mutex); 35 | if (_move_ranking.total_count > (uint64_t)num_reset_ranking) { 36 | _logger->info("\n{}", _move_ranking.info()); 37 | _move_ranking.reset(); 38 | } 39 | } 40 | 41 | void feedWinRate(float final_value) { 42 | std::lock_guard lock(_mutex); 43 | _win_rate_stats.feed(final_value); 44 | } 45 | 46 | void feedSgf(const std::string& sgf) { 47 | std::lock_guard lock(_mutex); 48 | _sgfs.push_back(sgf); 49 | } 50 | 51 | // For sender. 52 | WinRateStats getWinRateStats() { 53 | std::lock_guard lock(_mutex); 54 | return _win_rate_stats; 55 | } 56 | 57 | std::vector getPlayedGames() { 58 | std::lock_guard lock(_mutex); 59 | return _sgfs; 60 | } 61 | 62 | private: 63 | std::mutex _mutex; 64 | Ranking _move_ranking; 65 | WinRateStats _win_rate_stats; 66 | std::vector _sgfs; 67 | std::shared_ptr _logger; 68 | }; 69 | -------------------------------------------------------------------------------- /src_cpp/elfgames/go/common/model_pair.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "elf/ai/tree_search/tree_search_options.h" 5 | #include "elf/utils/json_utils.h" 6 | 7 | struct ModelPair { 8 | int64_t black_ver = -1; 9 | int64_t white_ver = -1; 10 | elf::ai::tree_search::TSOptions mcts_opt; 11 | 12 | bool wait() const { 13 | return black_ver < 0; 14 | } 15 | void set_wait() { 16 | black_ver = white_ver = -1; 17 | } 18 | 19 | bool is_selfplay() const { 20 | return black_ver >= 0 && white_ver == -1; 21 | } 22 | 23 | std::string info() const { 24 | std::stringstream ss; 25 | if (wait()) 26 | ss << "[wait]"; 27 | else if (is_selfplay()) 28 | ss << "[selfplay=" << black_ver << "]"; 29 | else 30 | ss << "[b=" << black_ver << "][w=" << white_ver << "]"; 31 | ss << mcts_opt.info(); 32 | return ss.str(); 33 | } 34 | 35 | friend bool operator==(const ModelPair& p1, const ModelPair& p2) { 36 | return p1.black_ver == p2.black_ver && p1.white_ver == p2.white_ver && 37 | p1.mcts_opt == p2.mcts_opt; 38 | } 39 | friend bool operator!=(const ModelPair& p1, const ModelPair& p2) { 40 | return !(p1 == p2); 41 | } 42 | 43 | void setJsonFields(json& j) const { 44 | JSON_SAVE(j, black_ver); 45 | JSON_SAVE(j, white_ver); 46 | JSON_SAVE_OBJ(j, mcts_opt); 47 | } 48 | 49 | static ModelPair createFromJson(const json& j) { 50 | ModelPair p; 51 | JSON_LOAD(p, j, black_ver); 52 | JSON_LOAD(p, j, white_ver); 53 | JSON_LOAD_OBJ(p, j, mcts_opt); 54 | return p; 55 | } 56 | }; 57 | 58 | namespace std { 59 | template <> 60 | struct hash { 61 | typedef ModelPair argument_type; 62 | typedef std::size_t result_type; 63 | result_type operator()(argument_type const& s) const noexcept { 64 | result_type const h1(std::hash{}(s.black_ver)); 65 | result_type const h2(std::hash{}(s.white_ver)); 66 | result_type const h3( 67 | std::hash{}(s.mcts_opt)); 68 | return h1 ^ (h2 << 1) ^ (h3 << 2); 69 | } 70 | }; 71 | } // namespace std 72 | -------------------------------------------------------------------------------- /src_cpp/elfgames/go/common/notifier.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../mcts/mcts.h" 4 | #include "elf/ai/tree_search/mcts.h" 5 | #include "go_state_ext.h" 6 | #include "record.h" 7 | 8 | class GameNotifierBase { 9 | public: 10 | using MCTSResult = elf::ai::tree_search::MCTSResultT; 11 | virtual void OnGameEnd(const GoStateExt&) {} 12 | virtual void OnStateUpdate(const ThreadState&) {} 13 | virtual void OnMCTSResult(Coord, const MCTSResult&) {} 14 | }; 15 | -------------------------------------------------------------------------------- /src_cpp/elfgames/go/inference/Pybind.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2018-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "game_context.h" 14 | 15 | namespace elfgames { 16 | namespace go { 17 | 18 | void registerPy(pybind11::module& m) { 19 | namespace py = pybind11; 20 | auto ref = py::return_value_policy::reference_internal; 21 | 22 | py::class_(m, "GameContext") 23 | .def(py::init()) 24 | .def("ctx", &GameContext::ctx, ref) 25 | .def("getParams", &GameContext::getParams) 26 | .def("getGame", &GameContext::getGame, ref) 27 | .def("setRequest", &GameContext::setRequest); 28 | 29 | // Also register other objects. 30 | PYCLASS_WITH_FIELDS(m, ContextOptions) 31 | .def(py::init<>()) 32 | .def("print", &ContextOptions::print); 33 | 34 | PYCLASS_WITH_FIELDS(m, GameOptions) 35 | .def(py::init<>()) 36 | .def("info", &GameOptions::info); 37 | 38 | py::class_(m, "GoGameSelfPlay") 39 | .def("showBoard", &GoGameSelfPlay::showBoard) 40 | .def("getNextPlayer", &GoGameSelfPlay::getNextPlayer) 41 | .def("getLastMove", &GoGameSelfPlay::getLastMove) 42 | .def("getScore", &GoGameSelfPlay::getScore) 43 | .def("getLastScore", &GoGameSelfPlay::getLastScore); 44 | } 45 | 46 | } // namespace go 47 | } // namespace elfgames 48 | -------------------------------------------------------------------------------- /src_cpp/elfgames/go/inference/Pybind.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2018-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | */ 8 | 9 | #pragma once 10 | 11 | #include 12 | 13 | namespace elfgames { 14 | namespace go { 15 | 16 | void registerPy(pybind11::module& m); 17 | 18 | } // namespace go 19 | } // namespace elfgames 20 | -------------------------------------------------------------------------------- /src_cpp/elfgames/go/inference/pybind_module.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2018-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | */ 8 | 9 | #include 10 | 11 | #include "Pybind.h" 12 | 13 | PYBIND11_MODULE(_elfgames_go_inference, m) { 14 | elfgames::go::registerPy(m); 15 | } 16 | -------------------------------------------------------------------------------- /src_cpp/elfgames/go/mcts/ai.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2018-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | */ 8 | 9 | #pragma once 10 | 11 | #include "elf/ai/ai.h" 12 | #include "elf/ai/tree_search/tree_search_base.h" 13 | 14 | #include "elfgames/go/base/go_state.h" 15 | 16 | using AI = elf::ai::AIClientT; 17 | 18 | namespace elf { 19 | namespace ai { 20 | namespace tree_search { 21 | 22 | template <> 23 | struct ActionTrait { 24 | public: 25 | static std::string to_string(const Coord& c) { 26 | return "[" + coord2str2(c) + "][" + coord2str(c) + "][" + 27 | std::to_string(c) + "]"; 28 | } 29 | static Coord default_value() { 30 | return M_INVALID; 31 | } 32 | }; 33 | 34 | template <> 35 | struct StateTrait { 36 | public: 37 | static std::string to_string(const GoState& s) { 38 | return "tt score (no komi): " + std::to_string(s.evaluate(0)); 39 | } 40 | static bool equals(const GoState& s1, const GoState& s2) { 41 | return s1.getHashCode() == s2.getHashCode(); 42 | } 43 | 44 | static bool moves_since( 45 | const GoState& s, 46 | size_t* next_move_number, 47 | std::vector* moves) { 48 | return s.moves_since(next_move_number, moves); 49 | } 50 | }; 51 | 52 | } // namespace tree_search 53 | } // namespace ai 54 | } // namespace elf 55 | -------------------------------------------------------------------------------- /src_cpp/elfgames/go/train/Pybind.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2018-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "game_context.h" 14 | 15 | namespace elfgames { 16 | namespace go { 17 | 18 | void registerPy(pybind11::module& m) { 19 | namespace py = pybind11; 20 | auto ref = py::return_value_policy::reference_internal; 21 | 22 | py::class_(m, "GameContext") 23 | .def(py::init()) 24 | .def("ctx", &GameContext::ctx, ref) 25 | .def("getParams", &GameContext::getParams) 26 | .def("getGame", &GameContext::getGame, ref) 27 | .def("getClient", &GameContext::getClient, ref) 28 | .def("getServer", &GameContext::getServer, ref); 29 | 30 | py::class_(m, "Server") 31 | .def("waitForSufficientSelfplay", &Server::waitForSufficientSelfplay) 32 | .def("notifyNewVersion", &Server::notifyNewVersion) 33 | .def("setInitialVersion", &Server::setInitialVersion) 34 | .def("setEvalMode", &Server::setEvalMode); 35 | 36 | py::class_(m, "Client") 37 | .def("setRequest", &Client::setRequest) 38 | .def("getGameStats", &Client::getGameStats, ref); 39 | 40 | // Also register other objects. 41 | PYCLASS_WITH_FIELDS(m, ContextOptions) 42 | .def(py::init<>()) 43 | .def("print", &ContextOptions::print); 44 | 45 | PYCLASS_WITH_FIELDS(m, GameOptions) 46 | .def(py::init<>()) 47 | .def("info", &GameOptions::info); 48 | 49 | PYCLASS_WITH_FIELDS(m, WinRateStats).def(py::init<>()); 50 | 51 | py::class_(m, "GameStats") 52 | .def("getWinRateStats", &GameStats::getWinRateStats) 53 | //.def("AllGamesFinished", &GameStats::AllGamesFinished) 54 | //.def("restartAllGames", &GameStats::restartAllGames) 55 | .def("getPlayedGames", &GameStats::getPlayedGames); 56 | 57 | py::class_(m, "GoGameSelfPlay") 58 | .def("showBoard", &GoGameSelfPlay::showBoard) 59 | .def("getNextPlayer", &GoGameSelfPlay::getNextPlayer) 60 | .def("getLastMove", &GoGameSelfPlay::getLastMove) 61 | .def("getScore", &GoGameSelfPlay::getScore) 62 | .def("getLastScore", &GoGameSelfPlay::getLastScore); 63 | } 64 | 65 | } // namespace go 66 | } // namespace elfgames 67 | -------------------------------------------------------------------------------- /src_cpp/elfgames/go/train/Pybind.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2018-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | */ 8 | 9 | #pragma once 10 | 11 | #include 12 | 13 | namespace elfgames { 14 | namespace go { 15 | 16 | void registerPy(pybind11::module& m); 17 | 18 | } // namespace go 19 | } // namespace elfgames 20 | -------------------------------------------------------------------------------- /src_cpp/elfgames/go/train/client_manager.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2018-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | */ 8 | 9 | #include "client_manager.h" 10 | 11 | ClientInfo::State::State(const ClientManager& mgr) : mgr_(mgr) { 12 | last_state_update_ = mgr_.getCurrTimeStamp(); 13 | } 14 | 15 | bool ClientInfo::State::CompareGame(const ModelPair& p) const { 16 | std::lock_guard lock(mutex_); 17 | return last_state_.black == p.black_ver && last_state_.white == p.white_ver; 18 | } 19 | 20 | bool ClientInfo::State::StateUpdate(const ThreadState& ts) { 21 | std::lock_guard lock(mutex_); 22 | if (last_state_ != ts) { 23 | last_state_ = ts; 24 | last_state_update_ = mgr_.getCurrTimeStamp(); 25 | return true; 26 | } else { 27 | return false; 28 | } 29 | } 30 | 31 | ClientInfo::ClientInfo( 32 | const ClientManager& mgr, 33 | const std::string& id, 34 | int num_threads, 35 | int max_delay_sec) 36 | : mgr_(mgr), identity_(id), max_delay_sec_(max_delay_sec), seq_(0) { 37 | for (int i = 0; i < num_threads; ++i) { 38 | threads_.emplace_back(new State(mgr_)); 39 | } 40 | last_update_ = mgr_.getCurrTimeStamp(); 41 | } 42 | 43 | void ClientInfo::stateUpdate(const ThreadState& ts) { 44 | std::lock_guard lock(mutex_); 45 | assert(ts.thread_id >= 0 && ts.thread_id < (int)threads_.size()); 46 | if (threads_[ts.thread_id]->StateUpdate(ts)) { 47 | last_update_ = mgr_.getCurrTimeStamp(); 48 | } 49 | } 50 | 51 | ClientInfo::ClientChange ClientInfo::updateActive() { 52 | std::lock_guard lock(mutex_); 53 | bool curr_active = (mgr_.getCurrTimeStamp() - last_update_ < max_delay_sec_); 54 | 55 | if (active_) { 56 | if (!curr_active) { 57 | active_ = false; 58 | return ALIVE2DEAD; 59 | } else { 60 | return ALIVE; 61 | } 62 | } else { 63 | if (curr_active) { 64 | active_ = true; 65 | return DEAD2ALIVE; 66 | } else { 67 | return DEAD; 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src_cpp/elfgames/go/train/distri_base.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "../common/record.h" 10 | #include "data_loader.h" 11 | #include "elf/base/context.h" 12 | #include "elf/legacy/python_options_utils_cpp.h" 13 | 14 | inline elf::shared::Options getNetOptions( 15 | const ContextOptions& contextOptions, 16 | const GameOptions& options) { 17 | elf::shared::Options netOptions; 18 | netOptions.addr = 19 | options.server_addr == "" ? "localhost" : options.server_addr; 20 | netOptions.port = options.port; 21 | netOptions.use_ipv6 = true; 22 | netOptions.verbose = options.verbose; 23 | netOptions.identity = contextOptions.job_id; 24 | 25 | return netOptions; 26 | } 27 | -------------------------------------------------------------------------------- /src_cpp/elfgames/go/train/game_train.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2018-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | */ 8 | 9 | #include "game_train.h" 10 | 11 | GoGameTrain::GoGameTrain( 12 | int game_idx, 13 | elf::GameClient* client, 14 | const ContextOptions& context_options, 15 | const GameOptions& options, 16 | elf::shared::ReaderQueuesT* reader) 17 | : GoGameBase(game_idx, client, context_options, options), reader_(reader) { 18 | for (size_t i = 0; i < kNumState; ++i) { 19 | _state_ext.emplace_back(new GoStateExtOffline(game_idx, options)); 20 | } 21 | } 22 | 23 | void GoGameTrain::act() { 24 | std::vector funcsToSend; 25 | 26 | for (size_t i = 0; i < kNumState; ++i) { 27 | while (true) { 28 | int q_idx; 29 | auto sampler = reader_->getSamplerWithParity(&_rng, &q_idx); 30 | const Record* r = sampler.sample(); 31 | if (r == nullptr) { 32 | continue; 33 | } 34 | _state_ext[i]->fromRecord(*r); 35 | 36 | // Random pick one ply. 37 | if (_state_ext[i]->switchRandomMove(&_rng)) 38 | break; 39 | } 40 | 41 | _state_ext[i]->generateD4Code(&_rng); 42 | 43 | // elf::FuncsWithState funcs = 44 | // client_->BindStateToFunctions({"train"}, &_state_ext); 45 | funcsToSend.push_back( 46 | client_->BindStateToFunctions({"train"}, _state_ext[i].get())); 47 | } 48 | 49 | // client_->sendWait({"train"}, &funcs); 50 | 51 | std::vector funcPtrsToSend(funcsToSend.size()); 52 | for (size_t i = 0; i < funcsToSend.size(); ++i) { 53 | funcPtrsToSend[i] = &funcsToSend[i]; 54 | } 55 | 56 | // VERY DANGEROUS - sending pointers of local objects to a function 57 | client_->sendBatchWait({"train"}, funcPtrsToSend); 58 | } 59 | -------------------------------------------------------------------------------- /src_cpp/elfgames/go/train/game_train.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2018-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | */ 8 | 9 | #include "../common/game_base.h" 10 | #include "elf/distributed/shared_reader.h" 11 | 12 | class GoGameTrain : public GoGameBase { 13 | public: 14 | GoGameTrain( 15 | int game_idx, 16 | elf::GameClient* client, 17 | const ContextOptions& context_options, 18 | const GameOptions& options, 19 | elf::shared::ReaderQueuesT* reader); 20 | 21 | void act() override; 22 | 23 | private: 24 | elf::shared::ReaderQueuesT* reader_ = nullptr; 25 | 26 | static constexpr size_t kNumState = 64; 27 | std::vector> _state_ext; 28 | }; 29 | -------------------------------------------------------------------------------- /src_cpp/elfgames/go/train/pybind_module.cc: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2018-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. 7 | */ 8 | 9 | #include 10 | 11 | #include "Pybind.h" 12 | 13 | PYBIND11_MODULE(_elfgames_go, m) { 14 | elfgames::go::registerPy(m); 15 | } 16 | -------------------------------------------------------------------------------- /src_py/elf/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2018-present, Facebook, Inc. 2 | # All rights reserved. 3 | # 4 | # This source code is licensed under the BSD-style license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | # C++ imports 8 | from _elf import * 9 | 10 | # Other imports 11 | from .context_utils import ContextArgs 12 | from .more_labels import MoreLabels 13 | from .utils_elf import GCWrapper, Batch 14 | from .zmq_util import ZMQSender, ZMQReceiver 15 | -------------------------------------------------------------------------------- /src_py/elf/logging/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2018-present, Facebook, Inc. 2 | # All rights reserved. 3 | # 4 | # This source code is licensed under the BSD-style license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | # Let's import C++ logging functions/classes as-is. 8 | 9 | from _elf._logging import * 10 | from .configuration import GlobalLoggingConfigurator 11 | -------------------------------------------------------------------------------- /src_py/elf/logging/configuration.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2018-present, Facebook, Inc. 2 | # All rights reserved. 3 | # 4 | # This source code is licensed under the BSD-style license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | from elf.options import auto_import_options, PyOptionSpec 8 | 9 | from . import LoggerLevel, set_level 10 | 11 | 12 | class GlobalLoggingConfigurator(object): 13 | """Global configurator for logging.""" 14 | @classmethod 15 | def get_option_spec(cls): 16 | spec = PyOptionSpec() 17 | spec.addStrOption( 18 | 'loglevel', 19 | ('Global log level. Choose from ' 20 | 'trace, debug, info, warning, error, critical, or off)'), 21 | 'info') 22 | return spec 23 | 24 | @auto_import_options 25 | def __init__(self, option_map): 26 | pass 27 | 28 | def configure(self): 29 | loglevel = LoggerLevel.from_str(self.options.loglevel) 30 | assert loglevel != LoggerLevel.invalid 31 | set_level(loglevel) 32 | -------------------------------------------------------------------------------- /src_py/elf/more_labels.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2018-present, Facebook, Inc. 2 | # All rights reserved. 3 | # 4 | # This source code is licensed under the BSD-style license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | from elf.options import auto_import_options, PyOptionSpec 8 | 9 | 10 | class MoreLabels(object): 11 | @classmethod 12 | def get_option_spec(cls): 13 | spec = PyOptionSpec() 14 | spec.addStrListOption( 15 | 'additional_labels', 16 | 'add additional labels in the batch; e.g. id, seq, last_terminal', 17 | []) 18 | return spec 19 | 20 | @auto_import_options 21 | def __init__(self, option_map): 22 | pass 23 | 24 | def add_labels(self, desc): 25 | if self.options.additional_labels: 26 | for _, v in desc.items(): 27 | v["input"].extend(self.options.additional_labels) 28 | -------------------------------------------------------------------------------- /src_py/elf/options/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2018-present, Facebook, Inc. 2 | # All rights reserved. 3 | # 4 | # This source code is licensed under the BSD-style license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | from .import_options import auto_import_options, import_options 8 | from .py_option_map import PyOptionMap 9 | from .py_option_spec import PyOptionSpec 10 | -------------------------------------------------------------------------------- /src_py/elf/options/import_options.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2018-present, Facebook, Inc. 2 | # All rights reserved. 3 | # 4 | # This source code is licensed under the BSD-style license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | import argparse 8 | 9 | 10 | def import_options(obj, option_map, option_spec, namespace=None): 11 | """Stores the parameters from a PyOptionMap into ``obj.options``.""" 12 | if namespace is None: 13 | setattr(obj, 'options', argparse.Namespace()) 14 | namespace = obj.options 15 | 16 | if option_spec is None: 17 | option_spec = option_map.getPyOptionSpec() 18 | 19 | option_map.storeIntoNamespace(namespace, option_spec) 20 | 21 | 22 | def auto_import_options(fn): 23 | """This decorator applies to __init__ methods where the first argument 24 | is a PyOptionMap. 25 | 26 | It copies each required argument (as specified by the class's 27 | ``get_option_spec()``) from the PyOptionMap into the object namespace 28 | of ``self.options`` (i.e. ``self.options.blah``). 29 | """ 30 | 31 | def call(self, option_map, *args, **kwargs): 32 | import_options(self, option_map, self.get_option_spec()) 33 | return fn(self, option_map, *args, **kwargs) 34 | 35 | return call 36 | -------------------------------------------------------------------------------- /src_py/elf/options/py_option_map.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2018-present, Facebook, Inc. 2 | # All rights reserved. 3 | # 4 | # This source code is licensed under the BSD-style license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | import json 8 | 9 | import elf 10 | from _elf import _options 11 | 12 | 13 | class PyOptionMap(_options.OptionMap): 14 | """Override C++ OptionMap with additional bells and whistles.""" 15 | 16 | def __init__(self, *args, **kwargs): 17 | super().__init__(*args, **kwargs) 18 | 19 | def getPyOptionSpec(self): 20 | return elf.options.PyOptionSpec(super().getOptionSpec()) 21 | 22 | def loadOptionDict(self, option_dict): 23 | return self.loadJSONString(json.dumps(option_dict)) 24 | 25 | def getOptionDict(self): 26 | return json.loads(self.getJSONString()) 27 | 28 | def get(self, option_name): 29 | return json.loads(self.getAsJSONString(option_name)) 30 | 31 | def storeIntoNamespace(self, namespace, option_spec=None): 32 | """Stores the parameters from a PyOptionMap into a namespace.""" 33 | if option_spec is None: 34 | option_spec = self.getPyOptionSpec() 35 | 36 | option_names = option_spec.getOptionNames() 37 | for name in option_names: 38 | setattr(namespace, name, self.get(name)) 39 | 40 | def clone(self): 41 | return PyOptionMap(self) 42 | 43 | def __deepcopy__(self, memo): 44 | return self.clone() 45 | -------------------------------------------------------------------------------- /src_py/elf/options/py_option_spec.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2018-present, Facebook, Inc. 2 | # All rights reserved. 3 | # 4 | # This source code is licensed under the BSD-style license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | import argparse 8 | import json 9 | import sys 10 | 11 | import elf 12 | from _elf import _options 13 | 14 | 15 | # We can get rid of this and just eval() the type name. 16 | # Depends on how safe we want to be. 17 | _typename_to_type = { 18 | 'str': str, 19 | 'int': int, 20 | 'float': float, 21 | 'bool': bool, 22 | } 23 | 24 | 25 | class PyOptionSpec(_options.OptionSpec): 26 | """Override C++ OptionSpec with additional bells and whistles.""" 27 | 28 | def __init__(self, *args, **kwargs): 29 | super().__init__(*args, **kwargs) 30 | 31 | def getArgparseOptions(self): 32 | return json.loads(self.getPythonArgparseOptionsAsJSONString()) 33 | 34 | def toArgparser(self): 35 | """Creates an ArgumentParser from a PyOptionSpec.""" 36 | parser = argparse.ArgumentParser() 37 | parser_options = self.getArgparseOptions() 38 | 39 | for parser_option in parser_options: 40 | if 'type' in parser_option['kwargs']: 41 | parser_option['kwargs']['type'] = \ 42 | _typename_to_type[parser_option['kwargs']['type']] 43 | parser.add_argument( 44 | *parser_option["args"], 45 | **parser_option["kwargs"]) 46 | 47 | return parser 48 | 49 | def parse(self, args=None, overrides=None): 50 | """Given a PyOptionSpec, parses the command line parameters 51 | (``sys.argv```) and returns the resulting PyOptionMap. 52 | 53 | ``args`` can override ``sys.argv`` and ``overrides`` can override 54 | any parsed items. 55 | """ 56 | 57 | parser = self.toArgparser() 58 | arg_namespace = parser.parse_args(args=args) 59 | 60 | if overrides: 61 | for k, v in overrides.items(): 62 | setattr(arg_namespace, k, v) 63 | 64 | arg_namespace.parsed_args = list(sys.argv if args is None else args) 65 | 66 | option_map = elf.options.PyOptionMap(self) 67 | option_map.loadOptionDict(vars(arg_namespace)) 68 | return option_map 69 | 70 | @classmethod 71 | def fromClasses(cls, classes): 72 | option_spec = cls() 73 | for c in classes: 74 | option_spec.merge(c.get_option_spec()) 75 | return option_spec 76 | 77 | def clone(self): 78 | return PyOptionSpec(self) 79 | 80 | def __deepcopy__(self, memo): 81 | return self.clone() 82 | -------------------------------------------------------------------------------- /src_py/elf/zmq_util.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2018-present, Facebook, Inc. 2 | # All rights reserved. 3 | # 4 | # This source code is licensed under the BSD-style license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | import zmq 8 | 9 | 10 | class ZMQCtx: 11 | def __init__(self): 12 | pass 13 | 14 | def __enter__(self): 15 | pass 16 | 17 | def __exit__(self, ty, value, tb): 18 | if value is not None: 19 | # print(value) 20 | pass 21 | return True 22 | # print("Send failed for " + self.identity + "..") 23 | 24 | 25 | class ZMQSender: 26 | def __init__(self, addr, identity, send_timeout=0, recv_timeout=0): 27 | self.ctx = zmq.Context() 28 | self.ctx.setsockopt(zmq.IPV6, 1) 29 | 30 | self.sender = self.ctx.socket(zmq.DEALER) 31 | self.sender.identity = identity.encode('ascii') 32 | # self.sender.set_hwm(10000) 33 | 34 | if send_timeout > 0: 35 | self.sender.SNDTIMEO = send_timeout 36 | if recv_timeout > 0: 37 | self.sender.RCVTIMEO = recv_timeout 38 | self.sender.connect(addr) 39 | 40 | def Send(self, msg, copy=False): 41 | with ZMQCtx(): 42 | self.sender.send(msg, copy=copy) 43 | return True 44 | return False 45 | 46 | def Receive(self): 47 | with ZMQCtx(): 48 | return self.sender.recv() 49 | return None 50 | 51 | 52 | class ZMQReceiver: 53 | def __init__(self, addr, timeout=0): 54 | self.ctx = zmq.Context() 55 | self.ctx.setsockopt(zmq.IPV6, 1) 56 | self.receiver = self.ctx.socket(zmq.ROUTER) 57 | # self.receiver.set_hwm(10000) 58 | 59 | if timeout > 0: 60 | self.receiver.RCVTIMEO = timeout 61 | self.receiver.bind(addr) 62 | 63 | def Send(self, identity, msg): 64 | with ZMQCtx(): 65 | self.receiver.send_multipart([identity, msg]) 66 | return True 67 | return False 68 | 69 | def Receive(self): 70 | # return identity, msg 71 | with ZMQCtx(): 72 | identity, msg = self.receiver.recv_multipart() 73 | # print(identity) 74 | # print(msg) 75 | return identity, msg 76 | return None, None 77 | -------------------------------------------------------------------------------- /src_py/elfgames/go/multiple_prediction.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2018-present, Facebook, Inc. 2 | # All rights reserved. 3 | # 4 | # This source code is licensed under the BSD-style license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | import torch.nn as nn 8 | from torch.autograd import Variable 9 | 10 | from elf.options import auto_import_options, PyOptionSpec 11 | from rlpytorch import add_err 12 | from rlpytorch.trainer import topk_accuracy 13 | 14 | 15 | class MultiplePrediction: 16 | @classmethod 17 | def get_option_spec(cls): 18 | spec = PyOptionSpec() 19 | spec.addBoolOption( 20 | 'multipred_backprop', 21 | 'Whether to backprop the total loss', 22 | True) 23 | return spec 24 | 25 | @auto_import_options 26 | def __init__(self, option_map): 27 | self.policy_loss = nn.NLLLoss().cuda() 28 | self.value_loss = nn.MSELoss().cuda() 29 | 30 | def update(self, mi, batch, stats): 31 | ''' Update given batch ''' 32 | # Current timestep. 33 | state_curr = mi["model"](batch) 34 | total_policy_loss = None 35 | eps = 1e-6 36 | targets = batch["offline_a"] 37 | if "pis" not in state_curr: 38 | state_curr["pis"] = [state_curr["pi"]] 39 | 40 | for i, pred in enumerate(state_curr["pis"]): 41 | if i == 0: 42 | prec1, prec5 = topk_accuracy( 43 | pred.data, targets[:, i].contiguous(), topk=(1, 5)) 44 | stats["top1_acc"].feed(prec1[0]) 45 | stats["top5_acc"].feed(prec5[0]) 46 | 47 | # backward. 48 | loss = self.policy_loss( 49 | (pred + eps).log(), Variable(targets[:, i])) 50 | stats["loss" + str(i)].feed(loss.data[0]) 51 | total_policy_loss = add_err(total_policy_loss, loss / (i + 1)) 52 | 53 | total_value_loss = None 54 | if "V" in state_curr and "winner" in batch: 55 | total_value_loss = self.value_loss( 56 | state_curr["V"], Variable(batch["winner"])) 57 | 58 | stats["total_policy_loss"].feed(total_policy_loss.data[0]) 59 | if total_value_loss is not None: 60 | stats["total_value_loss"].feed(total_value_loss.data[0]) 61 | total_loss = total_policy_loss + total_value_loss 62 | else: 63 | total_loss = total_policy_loss 64 | 65 | stats["total_loss"].feed(total_loss.data[0]) 66 | if self.options.multipred_backprop: 67 | total_loss.backward() 68 | -------------------------------------------------------------------------------- /src_py/rlpytorch/README.md: -------------------------------------------------------------------------------- 1 | # RLPyTorch: A Simple Reinforcement Learning Package in PyTorch 2 | 3 | Overview 4 | ============== 5 | Here we provide a simple reinforcement learning package as a backend for ELF. In the root directory there is basic framework for Rlpytorch. 6 | 7 | * `args_provider.py` 8 | Provide basic argument management mechanism. In RLPyTorch, each component (methods, model loader, etc) has its own argument set. 9 | Note that `args_utils.py` is a symlink for backward compatibility. 10 | 11 | * `model_base.py` 12 | Wrapper of `nn.Module`, providing save/load/counting steps etc. 13 | 14 | * `model_interface.py` 15 | Wrapper of multiple models. 16 | 17 | * `model_loader.py` 18 | Utility for loading saved models. 19 | 20 | In the subfolders there are multiple components in RLPyTorch: 21 | 22 | 1. `methods` 23 | Basic RL methods, e.g., PolicyGradient, ActorCritic, etc. Some methods are constructed from other basic ones. For example, `ActorCritic = PolicyGradient + DiscountedReward + ValueMatcher`. This makes the library easier to extend. For example, you might replace `DiscountedReward` with the final reward, which becomes REINFORCE. You might also replace it with Generalized Advantage Estimation (GAE) or $\lambda$-return, etc. 24 | 25 | 2. `trainer` 26 | Provider example callback functions for ELF framework. A simple example looks like the following: 27 | ``` 28 | GC.start() 29 | GC.reg_callback("train", train_callback) 30 | GC.reg_callback("actor", actor_callback) 31 | while True: 32 | GC.run() 33 | GC.stop() 34 | ``` 35 | The `GC.run()` function waits until the next batch with a specific tag arrives, then call registered callback functions. 36 | 37 | 3. `runner` 38 | Customize how to run the loop of `GC`. E.g., whether to run it with progress bar, in a single process or multiple processes, etc. 39 | 40 | 4. `sampler` 41 | Different ways to sample the actor model (to get the next action). 42 | 43 | 5. `stats` 44 | Supporting classes to collect various statistics. 45 | 46 | 6. `utils` 47 | Internal utilities. 48 | 49 | 50 | Actor Critic model 51 | ------------- 52 | We implemented advantageous actor-critic models, similar to Vanilla A3C, but with off-policy corrections with importance sampling. 53 | 54 | Specifically, we use the trajectory sampled from the previous version of the actor in the actor-critic update. 55 | -------------------------------------------------------------------------------- /src_py/rlpytorch/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2018-present, Facebook, Inc. 2 | # All rights reserved. 3 | # 4 | # This source code is licensed under the BSD-style license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | from .model_base import Model 8 | from .model_loader import ModelLoader, load_env 9 | from .model_interface import ModelInterface 10 | 11 | from .sampler import Sampler 12 | from .methods import ActorCritic, RNNActorCritic 13 | from .runner import EvalIters, EvalItersBasic, SingleProcessRun 14 | from .trainer import Trainer, Evaluator, LSTMTrainer 15 | 16 | from .methods import add_err, PolicyGradient, DiscountedReward, ValueMatcher 17 | -------------------------------------------------------------------------------- /src_py/rlpytorch/methods/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2018-present, Facebook, Inc. 2 | # All rights reserved. 3 | # 4 | # This source code is licensed under the BSD-style license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | from .actor_critic import ActorCritic 8 | from .rnn_actor_critic import RNNActorCritic 9 | from .q_learning import Q_learning 10 | from .policy_gradient import PolicyGradient 11 | from .discounted_reward import DiscountedReward 12 | from .value_matcher import ValueMatcher 13 | from .utils import add_err 14 | -------------------------------------------------------------------------------- /src_py/rlpytorch/methods/discounted_reward.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2018-present, Facebook, Inc. 2 | # All rights reserved. 3 | # 4 | # This source code is licensed under the BSD-style license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | from elf.options import auto_import_options, PyOptionSpec 8 | 9 | 10 | class DiscountedReward(object): 11 | @classmethod 12 | def get_option_spec(cls): 13 | spec = PyOptionSpec() 14 | spec.addFloatOption( 15 | 'discount', 16 | 'exponential discount rate', 17 | 0.99) 18 | return spec 19 | 20 | @auto_import_options 21 | def __init__(self, option_map): 22 | """Initialization of discounted reward.""" 23 | pass 24 | 25 | def setR(self, R, stats): 26 | """Set rewards and feed to stats.""" 27 | self.R = R 28 | stats["init_reward"].feed(R.mean()) 29 | 30 | def feed(self, batch, stats): 31 | """Update discounted reward and feed to stats. 32 | 33 | Keys in a batch: 34 | 35 | ``r`` (tensor): immediate reward. 36 | 37 | ``terminal`` (tensor): whether the current game has terminated. 38 | 39 | Feed to stats: immediate reward and accumulated reward 40 | """ 41 | r = batch["r"] 42 | term = batch["terminal"] 43 | 44 | # Compute the reward. 45 | self.R = self.R * self.options.discount + r 46 | 47 | # If we see any terminal signal, break the reward backpropagation 48 | # chain. 49 | for i, terminal in enumerate(term): 50 | if terminal: 51 | self.R[i] = r[i] 52 | 53 | stats["reward"].feed(r.mean()) 54 | stats["acc_reward"].feed(self.R.mean()) 55 | 56 | return self.R 57 | -------------------------------------------------------------------------------- /src_py/rlpytorch/methods/q_learning.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2018-present, Facebook, Inc. 2 | # All rights reserved. 3 | # 4 | # This source code is licensed under the BSD-style license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | import torch.nn as nn 8 | from torch.autograd import Variable 9 | 10 | from elf.options import auto_import_options, PyOptionSpec 11 | from .discounted_reward import DiscountedReward 12 | from .utils import add_err 13 | 14 | 15 | class Q_learning(object): 16 | """A Q-learning model.""" 17 | 18 | @classmethod 19 | def get_option_spec(cls): 20 | spec = PyOptionSpec() 21 | spec.addStrOption( 22 | 'a_node', 23 | 'action node', 24 | 'a') 25 | spec.addStrOption( 26 | 'q_node', 27 | 'Q node', 28 | 'Q') 29 | 30 | spec.merge(DiscountedReward.get_option_spec()) 31 | 32 | return spec 33 | 34 | @auto_import_options 35 | def __init__(self, option_map): 36 | """Initialization of q learning.""" 37 | self.discounted_reward = DiscountedReward(option_map) 38 | self.q_loss = nn.SmoothL1Loss().cuda() 39 | 40 | def update(self, mi, batch, stats): 41 | ''' Actor critic model update. 42 | Feed stats for later summarization. 43 | 44 | Args: 45 | mi(`ModelInterface`): mode interface used 46 | batch(dict): batch of data. Keys in a batch: 47 | ``s``: state, 48 | ``r``: immediate reward, 49 | ``terminal``: if game is terminated 50 | stats(`Stats`): Feed stats for later summarization. 51 | ''' 52 | m = mi["model"] 53 | Q_node = self.options.Q_node 54 | a_node = self.options.a_node 55 | 56 | T = batch["s"].size(0) 57 | 58 | state_curr = m(batch.hist(T - 1)) 59 | Q = state_curr[Q_node].squeeze().data 60 | V = Q.max(1) 61 | self.discounted_reward.setR(V, stats) 62 | 63 | err = None 64 | 65 | for t in range(T - 2, -1, -1): 66 | bht = batch.hist(t) 67 | state_curr = m.forward(bht) 68 | 69 | # go through the sample and get the rewards. 70 | Q = state_curr[Q_node].squeeze() 71 | a = state_curr[a_node].squeeze() 72 | 73 | R = self.discounted_reward.feed( 74 | dict(r=batch["r"][t], terminal=batch["terminal"][t]), 75 | stats=stats) 76 | 77 | # Then you want to match Q value here. 78 | # Q: batchsize * #action. 79 | Q_sel = Q.gather(1, a.view(-1, 1)).squeeze() 80 | err = add_err(err, nn.L2Loss(Q_sel, Variable(R))) 81 | 82 | stats["cost"].feed(err.data[0] / (T - 1)) 83 | err.backward() 84 | -------------------------------------------------------------------------------- /src_py/rlpytorch/methods/utils.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2018-present, Facebook, Inc. 2 | # All rights reserved. 3 | # 4 | # This source code is licensed under the BSD-style license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | 8 | def average_norm_clip(grad, clip_val): 9 | ''' 10 | Compute the norm and clip it if necessary. 11 | The first dimension will be batchsize. 12 | 13 | Args: 14 | grad(Tensor): the gradient 15 | clip_val(float): value to clip to 16 | ''' 17 | batchsize = grad.size(0) 18 | avg_l2_norm = 0.0 19 | for i in range(batchsize): 20 | avg_l2_norm += grad[i].data.norm() 21 | avg_l2_norm /= batchsize 22 | if avg_l2_norm > clip_val: 23 | # print("l2_norm: %.5f clipped to %.5f" % (avg_l2_norm, clip_val)) 24 | grad *= clip_val / avg_l2_norm 25 | 26 | 27 | def accumulate(acc, new): 28 | ''' accumulate by the same key in a list of dicts 29 | 30 | Args: 31 | acc(dict): the dict to accumulate to 32 | new(dict): new dict entry 33 | 34 | Returns: 35 | A new dict containing the accumulated sums of each key. 36 | ''' 37 | ret = {k: new[k] if a is None else a + new[k] 38 | for k, a in acc.items() if k in new} 39 | ret.update({k: v for k, v in new.items() if not (k in acc)}) 40 | return ret 41 | 42 | 43 | def add_err(overall_err, new_err): 44 | ''' Add ``new_err`` to ``overall_err`` 45 | 46 | Args: 47 | overall_err(float): summed overall error 48 | new_err(float): new error 49 | ''' 50 | if overall_err is None: 51 | return new_err 52 | else: 53 | overall_err += new_err 54 | return overall_err 55 | 56 | 57 | def add_stats(stats, key, value): 58 | ''' Feed ``value`` to ``stats[key]``''' 59 | if stats: 60 | stats[key].feed(value) 61 | 62 | 63 | def check_terminals(has_terminal, batch): 64 | ''' Check if the environment sent a terminal signal ''' 65 | # Block backpropagation if we go pass a terminal node. 66 | for i, terminal in enumerate(batch["terminal"]): 67 | if terminal: 68 | has_terminal[i] = True 69 | 70 | 71 | def check_terminals_anyT(has_terminal, batch, T): 72 | ''' Check if any of ``batch[t], t <= T`` is terminal''' 73 | for t in range(T): 74 | check_terminals(has_terminal, batch[t]) 75 | -------------------------------------------------------------------------------- /src_py/rlpytorch/methods/value_matcher.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2018-present, Facebook, Inc. 2 | # All rights reserved. 3 | # 4 | # This source code is licensed under the BSD-style license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | import torch.nn as nn 8 | from torch.autograd import Variable 9 | 10 | from elf.options import auto_import_options, PyOptionSpec 11 | 12 | from .utils import average_norm_clip 13 | 14 | 15 | class ValueMatcher(object): 16 | @classmethod 17 | def get_option_spec(cls): 18 | spec = PyOptionSpec() 19 | spec.addFloatOption( 20 | 'grad_clip_norm', 21 | 'gradient norm clipping', 22 | 0.0) 23 | spec.addStrOption( 24 | 'value_node', 25 | 'name of the value node', 26 | 'V') 27 | return spec 28 | 29 | @auto_import_options 30 | def __init__(self, option_map): 31 | """Initialization of value matcher. 32 | 33 | Initialize value loss to be ``nn.SmoothL1Loss``. 34 | """ 35 | self.value_loss = nn.SmoothL1Loss().cuda() 36 | 37 | def _reg_backward(self, v): 38 | ''' Register the backward hook. Clip the gradient if necessary.''' 39 | grad_clip_norm = self.options.grad_clip_norm 40 | if grad_clip_norm > 1e-20: 41 | def bw_hook(grad_in): 42 | grad = grad_in.clone() 43 | if grad_clip_norm is not None: 44 | average_norm_clip(grad, grad_clip_norm) 45 | return grad 46 | 47 | v.register_hook(bw_hook) 48 | 49 | def feed(self, batch, stats): 50 | """ 51 | One iteration of value match. 52 | 53 | nabla_w Loss(V - target) 54 | 55 | Keys in a batch: 56 | 57 | ``V`` (variable): value 58 | 59 | ``target`` (tensor): target value. 60 | 61 | Inputs that are of type Variable can backpropagate. 62 | 63 | Feed to stats: predicted value and value error 64 | 65 | Returns: 66 | value_err 67 | """ 68 | V = batch[self.options.value_node] 69 | value_err = self.value_loss(V, Variable(batch["target"])) 70 | self._reg_backward(V) 71 | stats["predicted_" + self.options.value_node].feed(V.data[0]) 72 | stats[self.options.value_node + "_err"].feed(value_err.data[0]) 73 | 74 | return value_err 75 | -------------------------------------------------------------------------------- /src_py/rlpytorch/runner/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2018-present, Facebook, Inc. 2 | # All rights reserved. 3 | # 4 | # This source code is licensed under the BSD-style license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | from .single_process import SingleProcessRun 8 | # from .multi_process import MultiProcessRun 9 | from .eval_iters import EvalIters, EvalItersBasic 10 | -------------------------------------------------------------------------------- /src_py/rlpytorch/sampler/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2018-present, Facebook, Inc. 2 | # All rights reserved. 3 | # 4 | # This source code is licensed under the BSD-style license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | from .sampler import Sampler 8 | from .sample_methods import sample_multinomial, epsilon_greedy 9 | -------------------------------------------------------------------------------- /src_py/rlpytorch/sampler/sampler.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2018-present, Facebook, Inc. 2 | # All rights reserved. 3 | # 4 | # This source code is licensed under the BSD-style license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | from elf.options import auto_import_options, PyOptionSpec 8 | from .sample_methods import sample_multinomial, epsilon_greedy 9 | 10 | 11 | class Sampler(object): 12 | @classmethod 13 | def get_option_spec(cls): 14 | spec = PyOptionSpec() 15 | spec.addStrOption( 16 | 'sample_policy', 17 | 'choices of epsilon-greedy, multinomial, or uniform', 18 | 'epsilon-greedy') 19 | spec.addBoolOption( 20 | 'store_greedy', 21 | ('if enabled, picks maximum-probability action; ' 22 | 'otherwise, sample from distribution'), 23 | False) 24 | spec.addFloatOption( 25 | 'epsilon', 26 | 'used in epsilon-greedy', 27 | 0.0) 28 | spec.addStrListOption( 29 | 'sample_nodes', 30 | 'nodes to be sampled and saved', 31 | ['pi,a']) 32 | return spec 33 | 34 | @auto_import_options 35 | def __init__(self, option_map): 36 | """Initialization for Sampler.""" 37 | self.sample_nodes = [] 38 | for nodes in self.options.sample_nodes: 39 | policy, action = nodes.split(",") 40 | self.sample_nodes.append((policy, action)) 41 | 42 | def sample(self, state_curr): 43 | """Sample an action from distribution using a certain sample method 44 | 45 | Args: 46 | state_curr(dict): current state containing all data 47 | """ 48 | # TODO: This only handles epsilon_greedy and multinomial for now. Add 49 | # uniform and original_distribution? 50 | sampler = (epsilon_greedy 51 | if self.options.store_greedy 52 | else sample_multinomial) 53 | 54 | actions = {} 55 | for pi_node, a_node in self.sample_nodes: 56 | actions[a_node] = sampler(state_curr, self.options, node=pi_node) 57 | actions[pi_node] = state_curr[pi_node].data 58 | return actions 59 | -------------------------------------------------------------------------------- /src_py/rlpytorch/stats/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2018-present, Facebook, Inc. 2 | # All rights reserved. 3 | # 4 | # This source code is licensed under the BSD-style license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | from .stats import EvalCount, RewardCount, WinRate, Stats 8 | -------------------------------------------------------------------------------- /src_py/rlpytorch/trainer/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2018-present, Facebook, Inc. 2 | # All rights reserved. 3 | # 4 | # This source code is licensed under the BSD-style license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | from .utils import ModelSaver, MultiCounter, topk_accuracy 8 | from .trainer import Trainer, Evaluator 9 | from .lstm_trainer import LSTMTrainer 10 | -------------------------------------------------------------------------------- /src_py/rlpytorch/trainer/timer.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2018-present, Facebook, Inc. 2 | # All rights reserved. 3 | # 4 | # This source code is licensed under the BSD-style license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | from datetime import datetime 8 | import time 9 | from collections import defaultdict 10 | 11 | 12 | class RLTimer: 13 | ''' A customized timer class''' 14 | 15 | def __init__(self): 16 | self.overall_counts = defaultdict(int) 17 | self.last_overall_mark = defaultdict(lambda: -1) 18 | self.restart() 19 | 20 | def restart(self): 21 | self.start_time = time.time() 22 | self.curr_time = datetime.now() 23 | self.durations = defaultdict(lambda: dict(duration=0, counter=0)) 24 | 25 | def record(self, name): 26 | curr_time = datetime.now() 27 | self.durations[name]["duration"] += (curr_time - 28 | self.curr_time).total_seconds() 29 | self.durations[name]["counter"] += 1 30 | self.overall_counts[name] += 1 31 | self.curr_time = curr_time 32 | 33 | def print(self, nstep): 34 | final_time = time.time() 35 | total_duration = (final_time - self.start_time) * 1000.0 / nstep 36 | s = ", ".join( 37 | "%s: %.3f ms" % 38 | (name, 39 | d["duration"] * 40 | 1000.0 / 41 | d["counter"]) for name, 42 | d in self.durations.items()) 43 | return "Total: %.3f ms. " % total_duration + s 44 | 45 | def printInterval(self, name, nstep, callback): 46 | if self.checkPeriodicCondition(name, nstep): 47 | callback(self) 48 | self.restart() 49 | self.updatePeriodicCondition(name) 50 | 51 | def checkPeriodicCondition(self, name, nstep): 52 | curr_count = self.overall_counts[name] 53 | last_count = self.last_overall_mark[name] 54 | return curr_count > last_count and curr_count % nstep == 0 55 | 56 | def updatePeriodicCondition(self, name): 57 | self.last_overall_mark[name] = self.overall_counts[name] 58 | 59 | def getPeriodicValue(self, name): 60 | return self.overall_counts[name] 61 | -------------------------------------------------------------------------------- /src_py/rlpytorch/utils/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2018-present, Facebook, Inc. 2 | # All rights reserved. 3 | # 4 | # This source code is licensed under the BSD-style license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | from .hist_states import HistState 8 | -------------------------------------------------------------------------------- /src_py/rlpytorch/utils/fp16_utils.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2018-present, Facebook, Inc. 2 | # All rights reserved. 3 | # 4 | # This source code is licensed under the BSD-style license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | import torch 8 | from rlpytorch import Model 9 | 10 | 11 | def apply_nonrecursive(module, fn): 12 | """Applies a given function only to parameters and buffers of a module. 13 | 14 | Adapted from torch.nn.Module._apply. 15 | """ 16 | for param in module._parameters.values(): 17 | if param is not None: 18 | # Tensors stored in modules are graph leaves, and we don't 19 | # want to create copy nodes, so we have to unpack the data. 20 | param.data = fn(param.data) 21 | if param._grad is not None: 22 | param._grad.data = fn(param._grad.data) 23 | 24 | for key, buf in module._buffers.items(): 25 | if buf is not None: 26 | module._buffers[key] = fn(buf) 27 | 28 | return module 29 | 30 | 31 | class FP16Model(Model): 32 | def __init__(self, option_map, params, model): 33 | super().__init__(option_map, params) 34 | 35 | self.model = model.float() 36 | for module in model.modules(): 37 | if not isinstance(module, torch.nn.modules.batchnorm._BatchNorm): 38 | apply_nonrecursive( 39 | module, lambda t: t.half() if t.is_floating_point() else t) 40 | 41 | def forward(self, input): 42 | fp16_input = input.half() 43 | return self.model(fp16_input) 44 | -------------------------------------------------------------------------------- /src_py/rlpytorch/utils/size_utils.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2018-present, Facebook, Inc. 2 | # All rights reserved. 3 | # 4 | # This source code is licensed under the BSD-style license found in the 5 | # LICENSE file in the root directory of this source tree. 6 | 7 | # From https://code.activestate.com/recipes/577504/ 8 | from __future__ import print_function 9 | from sys import getsizeof, stderr 10 | from itertools import chain 11 | from collections import deque 12 | try: 13 | from reprlib import repr 14 | except ImportError: 15 | pass 16 | 17 | 18 | def total_size(o, handlers={}, obj_handlers={}, verbose=False): 19 | """ Returns the approximate memory footprint an object and all of its contents. 20 | 21 | Automatically finds the contents of the following builtin containers and 22 | their subclasses: tuple, list, deque, dict, set and frozenset. 23 | To search other containers, add handlers to iterate over their contents: 24 | 25 | handlers = {SomeContainerClass: iter, 26 | OtherContainerClass: OtherContainerClass.get_elements} 27 | 28 | """ 29 | def dict_handler(d): return chain.from_iterable(d.items()) 30 | all_handlers = {tuple: iter, 31 | list: iter, 32 | deque: iter, 33 | dict: dict_handler, 34 | set: iter, 35 | frozenset: iter, 36 | } 37 | all_handlers.update(handlers) # user handlers take precedence 38 | seen = set() # track which object id's have already been seen 39 | # estimate sizeof object without __sizeof__ 40 | default_size = getsizeof(0) 41 | 42 | def sizeof(o): 43 | if id(o) in seen: # do not double count the same object 44 | return 0 45 | seen.add(id(o)) 46 | 47 | s = 0 48 | for typ, handler in obj_handlers.items(): 49 | if isinstance(o, typ): 50 | s = handler(o) 51 | break 52 | if s == 0: 53 | s = getsizeof(o, default_size) 54 | 55 | if verbose: 56 | print(s, type(o), repr(o), file=stderr) 57 | 58 | for typ, handler in all_handlers.items(): 59 | if isinstance(o, typ): 60 | s += sum(map(sizeof, handler(o))) 61 | break 62 | return s 63 | 64 | return sizeof(o) 65 | 66 | 67 | # Example call 68 | 69 | if __name__ == '__main__': 70 | d = dict(a=1, b=2, c=3, d=[4, 5, 6, 7], e='a string of chars') 71 | print(total_size(d, verbose=True)) 72 | -------------------------------------------------------------------------------- /third_party/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.3) 2 | 3 | # These projects all have CMakeLists by default, thank you devs! 4 | 5 | add_subdirectory(googletest) 6 | 7 | set_target_properties(gtest 8 | PROPERTIES 9 | DEBUG_POSTFIX "") 10 | add_subdirectory(json) 11 | add_subdirectory(pybind11) 12 | add_subdirectory(spdlog) 13 | 14 | # concurrent queue library 15 | 16 | add_library(concurrentqueue INTERFACE) 17 | target_include_directories(concurrentqueue SYSTEM INTERFACE 18 | concurrentqueue 19 | ) 20 | target_link_libraries(concurrentqueue INTERFACE 21 | ${CMAKE_THREAD_LIBS_INIT} 22 | ) 23 | 24 | # TBB 25 | 26 | set(TBB_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/tbb/) 27 | set(TBB_ROOT ${TBB_ROOT} PARENT_SCOPE) 28 | include(${TBB_ROOT}/cmake/TBBBuild.cmake) 29 | tbb_build( 30 | TBB_ROOT ${TBB_ROOT} 31 | MAKE_ARGS tbb_build_dir=${CMAKE_CURRENT_BINARY_DIR}/tbb/ 32 | CONFIG_DIR TBB_DIR) 33 | set(TBB_DIR ${TBB_DIR} PARENT_SCOPE) 34 | 35 | # Find ZMQ in system. TODO(maj): maybe use submodule? 36 | 37 | find_path(ZMQ_ROOT_DIR 38 | NAMES include/zmq.h) 39 | find_library(ZeroMQ_LIBRARY 40 | NAMES zmq libzmq 41 | HINTS ${ZMQ_ROOT_DIR}/lib 42 | ) 43 | find_path(ZeroMQ_INCLUDE_DIR 44 | NAMES zmq.h 45 | HINTS ${ZMQ_ROOT_DIR}/include 46 | ) 47 | add_library(zmq INTERFACE) 48 | target_include_directories(zmq SYSTEM INTERFACE ${ZeroMQ_INCLUDE_DIR}) 49 | target_link_libraries(zmq INTERFACE ${ZeroMQ_LIBRARY}) 50 | 51 | # C++ ZMQ 52 | 53 | add_library(cppzmq INTERFACE) 54 | target_include_directories(cppzmq SYSTEM INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/cppzmq/) 55 | target_link_libraries(cppzmq INTERFACE zmq) 56 | --------------------------------------------------------------------------------