Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

make it a bit easier to choose backend / algo from command line #15

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 56 additions & 77 deletions engine.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from lcztools import load_network, LeelaBoard
from lcztools import LeelaBoard, list_backends
import search
import chess
import chess.pgn
import sys

from leela_lite import get_search_algos

logfile = open("leelalite.log", "w")
LOG = False

Expand Down Expand Up @@ -40,77 +40,56 @@ def process_position(tokens):

return board

if len(sys.argv) == 3:
weights = sys.argv[1]
nodes = int(sys.argv[2])
type = "uct"
elif len(sys.argv) == 4:
weights = sys.argv[1]
nodes = int(sys.argv[2])
if sys.argv[3] == 'minimax':
type = 'minimax'
else:
type = 'uct'
else:
print("Usage: python3 engine.py <weights file or network server ID> <nodes>")
print(len(sys.argv))
exit(1)

network_id = None
try:
# If the parameter is an integer, assume it's a network server ID
network_id = int(weights)
weights = None
except:
pass

def load_leela_network():
global net, nn
if network_id is not None:
net = load_network(backend='net_client', network_id=network_id, policy_softmax_temp=2.2)
else:
net = load_network(backend='pytorch_cuda', filename=weights, policy_softmax_temp=2.2)
nn = search.NeuralNet(net=net, lru_size=max(5000, nodes))


send("Leela Lite")
board = LeelaBoard()
net = None
nn = None



while True:
line = sys.stdin.readline()
line = line.rstrip()
log("<{}".format(line))
tokens = line.split()
if len(tokens) == 0:
continue

if tokens[0] == "uci":
send('id name Leela Lite')
send('id author Dietrich Kappe')
send('uciok')
elif tokens[0] == "quit":
exit(0)
elif tokens[0] == "isready":
load_leela_network()
send("readyok")
elif tokens[0] == "ucinewgame":
board = LeelaBoard()
elif tokens[0] == 'position':
board = process_position(tokens)
elif tokens[0] == 'go':
my_nodes = nodes
if (len(tokens) == 3) and (tokens[1] == 'nodes'):
my_nodes = int(tokens[2])
if nn == None:
load_leela_network()
if type == 'uct':
best, node = search.UCT_search(board, my_nodes, net=nn, C=3.0)
else:
best, node = search.MinMax_search(board, my_nodes, net=nn, C=3.0)
send("bestmove {}".format(best))

logfile.close()
def uci(args):
from leela_lite import load_leela_network

send("Leela Lite")
board = LeelaBoard()

nodes = args.nodes
net = load_leela_network(args.weights, args.backend)
nn = search.NeuralNet(net=net, lru_size=min(5000, nodes))

search_func = get_search_algos()[args.algo]

while True:
line = sys.stdin.readline()
line = line.rstrip()
log("<{}".format(line))
tokens = line.split()
if len(tokens) == 0:
continue

if tokens[0] == "uci":
send('id name Leela Lite')
send('id author Dietrich Kappe')
send('uciok')
elif tokens[0] == "quit":
exit(0)
elif tokens[0] == "isready":
send("readyok")
elif tokens[0] == "ucinewgame":
board = LeelaBoard()
elif tokens[0] == 'position':
board = process_position(tokens)
elif tokens[0] == 'go':
my_nodes = nodes
if (len(tokens) == 3) and (tokens[1] == 'nodes'):
my_nodes = int(tokens[2])
best, node = search_func(board, my_nodes, net=nn, C=3.0)
send("bestmove {}".format(best))

logfile.close()

if __name__ == '__main__':
algos = get_search_algos().keys()

import argparse
parser = argparse.ArgumentParser(description='')
parser.add_argument('weights', help='weights file or network server ID')
parser.add_argument('nodes', type=int, help='nodes per move')
parser.add_argument('-a', '--algo', default='uct', help='search algo to use', choices=algos)
parser.add_argument('-b', '--backend', default='pytorch_cuda', choices=list_backends(), help='nn backend')

args = parser.parse_args()
uci(args)
110 changes: 59 additions & 51 deletions leela_lite.py
Original file line number Diff line number Diff line change
@@ -1,66 +1,74 @@
#!/usr/bin/python3
from lcztools import load_network, LeelaBoard
from lcztools import load_network, LeelaBoard, list_backends
import search
import chess
import chess.pgn
import sys
import time


if len(sys.argv) != 3:
print("Usage: python3 leela_lite.py <weights file or network server ID> <nodes>")
print(len(sys.argv))
exit(1)
else:
weights = sys.argv[1]
nodes = int(sys.argv[2])
def load_leela_network(weights, backend):
if backend == 'net_client':
network_id = int(weights)
return load_network(backend='net_client', network_id=network_id, policy_softmax_temp=2.2)

network_id = None
try:
# If the parameter is an integer, assume it's a network server ID
network_id = int(weights)
weights = None
except:
pass
return load_network(backend=backend, filename=weights, policy_softmax_temp=2.2)

def load_leela_network():
global net, nn
if network_id is not None:
net = load_network(backend='net_client', network_id=network_id, policy_softmax_temp=2.2)
else:
net = load_network(backend='pytorch_cuda', filename=weights, policy_softmax_temp=2.2)
def get_search_algos():
from inspect import getmembers, isfunction

methods = {}
for key, value in getmembers(search, isfunction):
if key.endswith('_search'):
methods[key.rsplit('_',1)[0].lower()] = value
return methods

def play(args):
nodes = args.nodes
net = load_leela_network(args.weights, args.backend)
nn = search.NeuralNet(net=net, lru_size=min(5000, nodes))


load_leela_network()
search_func = get_search_algos()[args.algo]

SELFPLAY = True
SELFPLAY = True

board = LeelaBoard()
while True:
if not SELFPLAY:
print(board.unicode())
print("Enter move: ", end='')
sys.stdout.flush()
line = sys.stdin.readline()
line = line.rstrip()
board.push_uci(line)
print(board.unicode())
print("thinking...")
start = time.time()
best, node = search.UCT_search(board, nodes, net=nn, C=3.4)
elapsed = time.time() - start
print("best: ", best)
print("Time: {:.3f} nps".format(nodes/elapsed))
print(nn.evaluate.cache_info())
board.push_uci(best)
if board.pc_board.is_game_over() or board.is_draw():
result = board.pc_board.result(claim_draw=True)
print("Game over... result is {}".format(result))
board = LeelaBoard()
while True:
if not SELFPLAY:
print(board.unicode())
print("Enter move: ", end='')
sys.stdout.flush()
line = sys.stdin.readline()
line = line.rstrip()
board.push_uci(line)
print(board.unicode())
print()
pgn_game = chess.pgn.Game.from_board(board.pc_board)
pgn_game.headers['Result'] = result
print(pgn_game)
break

print("thinking...")
start = time.time()
best, node = search_func(board, nodes, net=nn, C=3.4)
elapsed = time.time() - start
print("best: ", best)
print("Time: {:.3f} nps".format(nodes/elapsed))
print(nn.evaluate.cache_info())
board.push_uci(best)
if board.pc_board.is_game_over() or board.is_draw():
result = board.pc_board.result(claim_draw=True)
print("Game over... result is {}".format(result))
print(board.unicode())
print()
pgn_game = chess.pgn.Game.from_board(board.pc_board)
pgn_game.headers['Result'] = result
print(pgn_game)
break

if __name__ == '__main__':
algos = get_search_algos().keys()

import argparse
parser = argparse.ArgumentParser(description='')
parser.add_argument('weights', help='weights file or network server ID')
parser.add_argument('nodes', type=int, help='nodes per move')
parser.add_argument('-a', '--algo', default='uct', help='search algo to use', choices=algos)
parser.add_argument('-b', '--backend', default='pytorch_cuda', choices=list_backends(), help='nn backend')

args = parser.parse_args()
play(args)