formatted

This commit is contained in:
Nemo D'ACREMONT 2025-05-18 19:51:57 +02:00
parent 0e4d30fa0d
commit 91cf372a7e
No known key found for this signature in database
GPG Key ID: 85F245EC3BB1E022
2 changed files with 57 additions and 53 deletions

View File

@ -4,6 +4,7 @@ import math
from typing import Any, Callable from typing import Any, Callable
import Goban import Goban
def _alphabeta( def _alphabeta(
board: Goban.Board, board: Goban.Board,
heuristic: Callable[[Goban.Board, Any], float], heuristic: Callable[[Goban.Board, Any], float],
@ -11,12 +12,12 @@ def _alphabeta(
alpha=-math.inf, alpha=-math.inf,
beta=math.inf, beta=math.inf,
depth: int = 3, depth: int = 3,
shouldStop=lambda: False shouldStop=lambda: False,
) -> tuple[float, Any]: ) -> tuple[float, Any]:
if board.is_game_over() or depth == 0: if board.is_game_over() or depth == 0:
return heuristic(board, color), None return heuristic(board, color), None
wantMax = (board.next_player() == color) wantMax = board.next_player() == color
best_move = None best_move = None
if wantMax: if wantMax:
@ -33,7 +34,7 @@ def _alphabeta(
alpha=alpha, alpha=alpha,
beta=beta, beta=beta,
depth=depth - 1, depth=depth - 1,
shouldStop=shouldStop shouldStop=shouldStop,
)[0] )[0]
board.pop() board.pop()
@ -59,7 +60,7 @@ def _alphabeta(
alpha=alpha, alpha=alpha,
beta=beta, beta=beta,
depth=depth - 1, depth=depth - 1,
shouldStop=shouldStop shouldStop=shouldStop,
)[0] )[0]
board.pop() board.pop()
@ -73,6 +74,7 @@ def _alphabeta(
return acc, best_move return acc, best_move
def alphabeta( def alphabeta(
board: Goban.Board, board: Goban.Board,
heuristic: Callable[[Goban.Board, Any], float], heuristic: Callable[[Goban.Board, Any], float],
@ -88,7 +90,7 @@ def IDDFS(
heuristic: Callable[[Goban.Board, Any], float], heuristic: Callable[[Goban.Board, Any], float],
color, color,
max_depth: int = 10, max_depth: int = 10,
duration: float = 5.0 # Duration in seconds duration: float = 5.0, # Duration in seconds
): ):
best_move = None best_move = None
start_time = time.time() start_time = time.time()
@ -97,11 +99,7 @@ def IDDFS(
for depth in range(1, max_depth + 1): for depth in range(1, max_depth + 1):
value, move = _alphabeta( value, move = _alphabeta(
board, board, heuristic=heuristic, color=color, depth=depth, shouldStop=shouldStop
heuristic=heuristic,
color=color,
depth=depth,
shouldStop=shouldStop
) )
if shouldStop(): if shouldStop():

View File

@ -19,6 +19,7 @@ import numpy as np
from torch.utils.data import Dataset from torch.utils.data import Dataset
import json import json
def setup_device(): def setup_device():
# Allows to use the GPU if available # Allows to use the GPU if available
if torch.cuda.is_available(): if torch.cuda.is_available():
@ -36,7 +37,7 @@ def goban2Go(board: Goban.Board):
Convert a goban board to a tensor for the model Convert a goban board to a tensor for the model
""" """
goBoard = torch.zeros((3, 8, 8), dtype=torch.float32) goBoard = torch.zeros((3, 8, 8), dtype=torch.float32)
black_plays = (board.next_player() == Goban.Board._BLACK) black_plays = board.next_player() == Goban.Board._BLACK
flat = board.get_board() flat = board.get_board()
for i in range(8): for i in range(8):
@ -46,7 +47,7 @@ def goban2Go(board: Goban.Board):
elif flat[i * 8 + j] == Goban.Board._WHITE: elif flat[i * 8 + j] == Goban.Board._WHITE:
goBoard[1, i, j] = 1 goBoard[1, i, j] = 1
goBoard[2,:,:] = 1 if black_plays else 0 goBoard[2, :, :] = 1 if black_plays else 0
return goBoard return goBoard
@ -56,50 +57,44 @@ class GoModel(nn.Module):
super(GoModel, self).__init__() super(GoModel, self).__init__()
self.net = torch.nn.Sequential( self.net = torch.nn.Sequential(
nn.Conv2d(3, 16, kernel_size=3, padding=1, bias=False), nn.Conv2d(3, 16, kernel_size=3, padding=1, bias=False),
nn.BatchNorm2d(16), nn.BatchNorm2d(16),
torch.nn.ReLU(), torch.nn.ReLU(),
nn.Conv2d(16, 32, kernel_size=3, padding=1, bias=False),
nn.Conv2d(16, 32, kernel_size=3, padding=1, bias=False), nn.BatchNorm2d(32),
nn.BatchNorm2d(32), torch.nn.ReLU(),
torch.nn.ReLU(), nn.Conv2d(32, 64, kernel_size=3, padding=1, bias=False),
nn.BatchNorm2d(64),
nn.Conv2d(32, 64, kernel_size=3, padding=1, bias=False), nn.Dropout(0.4),
nn.BatchNorm2d(64), torch.nn.ReLU(),
nn.Dropout(0.4), nn.Conv2d(64, 128, kernel_size=3, padding=1, bias=False),
torch.nn.ReLU(), nn.BatchNorm2d(128),
torch.nn.ReLU(),
nn.Conv2d(64, 128, kernel_size=3, padding=1, bias=False), nn.Conv2d(128, 128, kernel_size=3, padding=1, bias=False),
nn.BatchNorm2d(128), nn.BatchNorm2d(128),
torch.nn.ReLU(), torch.nn.ReLU(),
nn.Conv2d(128, 128, kernel_size=3, padding=1, bias=False),
nn.Conv2d(128, 128, kernel_size=3, padding=1, bias=False), nn.BatchNorm2d(128),
nn.BatchNorm2d(128), torch.nn.ReLU(),
torch.nn.ReLU(), nn.Flatten(),
nn.Linear(128 * 8 * 8, 128),
nn.Conv2d(128, 128, kernel_size=3, padding=1, bias=False), nn.BatchNorm1d(128),
nn.BatchNorm2d(128), torch.nn.ReLU(),
torch.nn.ReLU(), nn.Dropout(0.4),
nn.Linear(128, 1),
nn.Flatten(), nn.Sigmoid(),
nn.Linear(128 * 8 * 8, 128),
nn.BatchNorm1d(128),
torch.nn.ReLU(),
nn.Dropout(0.4),
nn.Linear(128, 1),
nn.Sigmoid()
) )
def forward(self, x): def forward(self, x):
if self.training: if self.training:
return self.net(x) return self.net(x)
else: else:
y = self.net(x) y = self.net(x)
batch_size = x.size(0) batch_size = x.size(0)
x_rotated = torch.stack([torch.rot90(x, k=k, dims=[2, 3]) for k in range(4)], dim=1) # x_rotated: [batch_size, 4, 3, 8, 8] x_rotated = torch.stack(
[torch.rot90(x, k=k, dims=[2, 3]) for k in range(4)], dim=1
) # x_rotated: [batch_size, 4, 3, 8, 8]
x_rotated = x_rotated.view(-1, 3, 8, 8) # [batch_size*4, 3, 8, 8] x_rotated = x_rotated.view(-1, 3, 8, 8) # [batch_size*4, 3, 8, 8]
with torch.no_grad(): with torch.no_grad():
@ -107,7 +102,7 @@ class GoModel(nn.Module):
# Reshape to get them by rotation # Reshape to get them by rotation
y_rotated = y_rotated.view(batch_size, 4, -1) # [batch_size, 4, 1] y_rotated = y_rotated.view(batch_size, 4, -1) # [batch_size, 4, 1]
y_mean = y_rotated.mean(dim=1) # [batch_size, 1] y_mean = y_rotated.mean(dim=1) # [batch_size, 1]
return y_mean return y_mean
@ -193,24 +188,35 @@ class myPlayer(PlayerInterface):
b, w = self._board.compute_score() b, w = self._board.compute_score()
# If passing wins the game, pass # If passing wins the game, pass
if self.last_op_move == -1 and (b - w) * (1 if self._mycolor == Goban.Board._BLACK else -1) > 0: if (
self.last_op_move == -1
and (b - w) * (1 if self._mycolor == Goban.Board._BLACK else -1) > 0
):
move = -1 move = -1
# Play greedily opening moves early in the game # Play greedily opening moves early in the game
elif self._board._nbBLACK + self._board._nbWHITE < 10: elif self._board._nbBLACK + self._board._nbWHITE < 10:
turn = self._board._nbBLACK + self._board._nbWHITE turn = self._board._nbBLACK + self._board._nbWHITE
for play in self.plays: for play in self.plays:
if len(play["moves"]) > turn and Goban.Board.name_to_flat(play["moves"][turn]) in self._board.legal_moves(): if (
len(play["moves"]) > turn
and Goban.Board.name_to_flat(play["moves"][turn])
in self._board.legal_moves()
):
move = Goban.Board.name_to_flat(play["moves"][turn]) move = Goban.Board.name_to_flat(play["moves"][turn])
# Use iddfs alphabeta # Use iddfs alphabeta
else: else:
move = IDDFS( move = IDDFS(
self._board, self.nnheuristic, self._mycolor, duration=duration, max_depth=64 self._board,
self.nnheuristic,
self._mycolor,
duration=duration,
max_depth=64,
) )
nd = time.time() nd = time.time()
self.time += (nd - st) self.time += nd - st
print(move, (nd - st), file=stderr) print(move, (nd - st), file=stderr)