From 31199c7d0d9d55421da2adce90bd014c425db80e Mon Sep 17 00:00:00 2001 From: Dong Yan Date: Sat, 16 Dec 2017 23:29:11 +0800 Subject: [PATCH] 0. code refactor, try to merge Go and GoEnv --- AlphaGo/game.py | 41 ++++++++++++++------------- AlphaGo/go.py | 2 +- AlphaGo/play.py | 4 +-- AlphaGo/strategy.py | 57 +++++++++++++++++++++----------------- tianshou/core/mcts/mcts.py | 2 +- 5 files changed, 57 insertions(+), 49 deletions(-) diff --git a/AlphaGo/game.py b/AlphaGo/game.py index 360921e..02ccb27 100644 --- a/AlphaGo/game.py +++ b/AlphaGo/game.py @@ -31,14 +31,14 @@ class Game: self.komi = komi self.board = [utils.EMPTY] * (self.size * self.size) self.history = [] - self.past = deque(maxlen=8) + self.latest_boards = deque(maxlen=8) for _ in range(8): - self.past.append(self.board) + self.latest_boards.append(self.board) self.executor = go.Go(game=self) #self.strategy = strategy(checkpoint_path) - self.simulator = strategy.GoEnv() + self.simulator = strategy.GoEnv(game=self) self.net = network_small.Network() self.sess = self.net.forward(checkpoint_path) self.evaluator = lambda state: self.sess.run([tf.nn.softmax(self.net.p), self.net.v], @@ -57,7 +57,7 @@ class Game: self.board = [utils.EMPTY] * (self.size * self.size) self.history = [] for _ in range(8): - self.past.append(self.board) + self.latest_boards.append(self.board) def set_size(self, n): self.size = n @@ -66,29 +66,29 @@ class Game: def set_komi(self, k): self.komi = k - def data_process(self, history, color): - state = np.zeros([1, self.simulator.size, self.simulator.size, 17]) + def generate_nn_input(self, history, color): + state = np.zeros([1, self.size, self.size, 17]) for i in range(8): - state[0, :, :, i] = np.array(np.array(history[i]) == np.ones(self.simulator.size ** 2)).reshape(self.simulator.size, self.simulator.size) - state[0, :, :, i + 8] = np.array(np.array(history[i]) == -np.ones(self.simulator.size ** 2)).reshape(self.simulator.size, self.simulator.size) + state[0, :, :, i] = np.array(np.array(history[i]) == np.ones(self.size ** 2)).reshape(self.size, self.size) + state[0, :, :, i + 8] = np.array(np.array(history[i]) == -np.ones(self.size ** 2)).reshape(self.size, self.size) if color == utils.BLACK: - state[0, :, :, 16] = np.ones([self.simulator.size, self.simulator.size]) + state[0, :, :, 16] = np.ones([self.size, self.size]) if color == utils.WHITE: - state[0, :, :, 16] = np.zeros([self.simulator.size, self.simulator.size]) + state[0, :, :, 16] = np.zeros([self.size, self.size]) return state - def strategy_gen_move(self, history, color): - self.simulator.history = copy.copy(history) - self.simulator.board = copy.copy(history[-1]) - state = self.data_process(self.simulator.history, color) - mcts = MCTS(self.simulator, self.evaluator, state, self.simulator.size ** 2 + 1, inverse=True, max_step=10) + def strategy_gen_move(self, latest_boards, color): + self.simulator.latest_boards = copy.copy(latest_boards) + self.simulator.board = copy.copy(latest_boards[-1]) + nn_input = self.generate_nn_input(self.simulator.latest_boards, color) + mcts = MCTS(self.simulator, self.evaluator, nn_input, self.size ** 2 + 1, inverse=True, max_step=1) temp = 1 prob = mcts.root.N ** temp / np.sum(mcts.root.N ** temp) - choice = np.random.choice(self.simulator.size ** 2 + 1, 1, p=prob).tolist()[0] - if choice == self.simulator.size ** 2: + choice = np.random.choice(self.size ** 2 + 1, 1, p=prob).tolist()[0] + if choice == self.size ** 2: move = utils.PASS else: - move = (choice % self.simulator.size + 1, choice / self.simulator.size + 1) + move = (choice % self.size + 1, choice / self.size + 1) return move, prob def do_move(self, color, vertex): @@ -100,7 +100,7 @@ class Game: def gen_move(self, color): # move = self.strategy.gen_move(color) # return move - move, self.prob = self.strategy_gen_move(self.past, color) + move, self.prob = self.strategy_gen_move(self.latest_boards, color) self.do_move(color, move) return move @@ -127,3 +127,6 @@ class Game: if __name__ == "__main__": g = Game() g.show_board() + #file = open("debug.txt", "a") + #file.write("mcts check\n") + #file.close() diff --git a/AlphaGo/go.py b/AlphaGo/go.py index 26540e1..0afc877 100644 --- a/AlphaGo/go.py +++ b/AlphaGo/go.py @@ -135,7 +135,7 @@ class Go: self.game.board[self.game._flatten(vertex)] = color self._process_board(color, vertex) self.game.history.append(copy.copy(self.game.board)) - self.game.past.append(copy.copy(self.game.board)) + self.game.latest_boards.append(copy.copy(self.game.board)) return True def _find_empty(self): diff --git a/AlphaGo/play.py b/AlphaGo/play.py index d6e6138..fe6c7ce 100644 --- a/AlphaGo/play.py +++ b/AlphaGo/play.py @@ -87,8 +87,8 @@ if __name__ == '__main__': score = player[turn].run_cmd(str(num) + ' get_score') print "Finished : ", score.split(" ")[1] player[0].run_cmd(str(num) + ' clear_board') - player[1].run_cmd(str(num) + ' clear_board') - game_num += 1 + player[1].run_cmd(str(num) + ' clear_board') + game_num += 1 subprocess.call(["kill", "-9", str(agent_v0.pid)]) subprocess.call(["kill", "-9", str(agent_v1.pid)]) diff --git a/AlphaGo/strategy.py b/AlphaGo/strategy.py index 5a55002..0bad998 100644 --- a/AlphaGo/strategy.py +++ b/AlphaGo/strategy.py @@ -14,15 +14,14 @@ DELTA = [[1, 0], [-1, 0], [0, -1], [0, 1]] CORNER_OFFSET = [[-1, -1], [-1, 1], [1, 1], [1, -1]] class GoEnv: - def __init__(self, size=9, komi=6.5): - self.size = size - self.komi = komi - self.board = [utils.EMPTY] * (self.size * self.size) - self.history = deque(maxlen=8) + def __init__(self, **kwargs): + self.game = kwargs['game'] + self.board = [utils.EMPTY] * (self.game.size * self.game.size) + self.latest_boards = deque(maxlen=8) def _flatten(self, vertex): x, y = vertex - return (x - 1) * self.size + (y - 1) + return (x - 1) * self.game.size + (y - 1) def _bfs(self, vertex, color, block, status, alive_break): block.append(vertex) @@ -35,7 +34,7 @@ class GoEnv: def _find_block(self, vertex, alive_break=False): block = [] - status = [False] * (self.size * self.size) + status = [False] * (self.game.size * self.game.size) color = self.board[self._flatten(vertex)] self._bfs(vertex, color, block, status, alive_break) @@ -73,7 +72,7 @@ class GoEnv: _board = copy.copy(self.board) self.board[self._flatten(vertex)] = color self._process_board(color, vertex) - if self.board in self.history: + if self.board in self.latest_boards: res = True else: res = False @@ -83,8 +82,8 @@ class GoEnv: def _in_board(self, vertex): x, y = vertex - if x < 1 or x > self.size: return False - if y < 1 or y > self.size: return False + if x < 1 or x > self.game.size: return False + if y < 1 or y > self.game.size: return False return True def _neighbor(self, vertex): @@ -151,21 +150,28 @@ class GoEnv: # print "many opponents, fake eye" return False - # def is_valid(self, color, vertex): - def is_valid(self, state, action): + def knowledge_prunning(self, color, vertex): + ### check if it is an eye of yourself + ### assumptions : notice that this judgement requires that the state is an endgame + if self._is_eye(color, vertex): + return False + return True + + def simulate_is_valid(self, state, action): # state is the play board, the shape is [1, 9, 9, 17] - if action == self.size * self.size: + if action == self.game.size * self.game.size: vertex = (0, 0) else: - vertex = (action / self.size + 1, action % self.size + 1) + vertex = (action / self.game.size + 1, action % self.game.size + 1) if state[0, 0, 0, -1] == utils.BLACK: color = utils.BLACK else: color = utils.WHITE - self.history.clear() + self.latest_boards.clear() for i in range(8): - self.history.append((state[:, :, :, i] - state[:, :, :, i + 8]).reshape(-1).tolist()) - self.board = copy.copy(self.history[-1]) + self.latest_boards.append((state[:, :, :, i] - state[:, :, :, i + 8]).reshape(-1).tolist()) + self.board = copy.copy(self.latest_boards[-1]) + ### in board if not self._in_board(vertex): return False @@ -180,12 +186,11 @@ class GoEnv: if not self._is_qi(color, vertex): return False - ### check if it is an eye of yourself - ### assumptions : notice that this judgement requires that the state is an endgame - if self._is_eye(color, vertex): + ### forbid global isomorphous + if self._check_global_isomorphous(color, vertex): return False - if self._check_global_isomorphous(color, vertex): + if not self.knowledge_prunning(color, vertex): return False return True @@ -206,17 +211,17 @@ class GoEnv: color = utils.BLACK else: color = utils.WHITE - if action == self.size ** 2: + if action == self.game.size ** 2: vertex = utils.PASS else: - vertex = (action % self.size + 1, action / self.size + 1) + vertex = (action % self.game.size + 1, action / self.game.size + 1) # print(vertex) # print(self.board) self.board = (state[:, :, :, 7] - state[:, :, :, 15]).reshape(-1).tolist() self.do_move(color, vertex) new_state = np.concatenate( - [state[:, :, :, 1:8], (np.array(self.board) == utils.BLACK).reshape(1, self.size, self.size, 1), - state[:, :, :, 9:16], (np.array(self.board) == utils.WHITE).reshape(1, self.size, self.size, 1), - np.array(1 - state[:, :, :, -1]).reshape(1, self.size, self.size, 1)], + [state[:, :, :, 1:8], (np.array(self.board) == utils.BLACK).reshape(1, self.game.size, self.game.size, 1), + state[:, :, :, 9:16], (np.array(self.board) == utils.WHITE).reshape(1, self.game.size, self.game.size, 1), + np.array(1 - state[:, :, :, -1]).reshape(1, self.game.size, self.game.size, 1)], axis=3) return new_state, 0 diff --git a/tianshou/core/mcts/mcts.py b/tianshou/core/mcts/mcts.py index 47b0768..979e994 100644 --- a/tianshou/core/mcts/mcts.py +++ b/tianshou/core/mcts/mcts.py @@ -75,7 +75,7 @@ class UCTNode(MCTSNode): start_time = time.time() self.mask = [] for act in range(self.action_num - 1): - if not simulator.is_valid(self.state, act): + if not simulator.simulate_is_valid(self.state, act): self.mask.append(act) self.ucb[act] = -float("Inf") else: