def _decode_node(self, reader, depth=0): row = next(reader) node = MonteCarloNode() d = node.details d.move_name = row[0] d.visits_count = int(row[1]) d.visits_count_pre_modified = int(row[2]) d.average_prize = float(row[3]) d.state_name = row[4] children = int(row[5]) for i in range(children): child = self._decode_node(reader, depth + 1) node.add_child_by_node(child) return node
def _decode_node(self, file): rc = MonteCarloNode() state_name = BinaryCodec.read_string(file) rc.details.state_name = state_name children_count = BinaryCodec.read_integer(file) for i in range(children_count): details = MonteCarloNodeDetails() details.move_name = BinaryCodec.read_string(file) details.visits_count = BinaryCodec.read_integer(file) details.visits_count_pre_modified = BinaryCodec.read_integer(file) details.average_prize = BinaryCodec.read_float(file) child, child_state_name = self._decode_node(file) details.state_name = child_state_name child.details = details rc.add_child_by_node(child) return rc, state_name
def create_node(name, move_name): n = MonteCarloNode() n.details.state_name = name if len(move_name) > 0: n.details.move = move_name n.details.visits_count = 3 n.details.visits_count_pre_modified = 4 n.details.average_prize = 4.5 return n
def __init__(self, game_state: BaseGameState = None, root: MonteCarloNode = None): if game_state is not None: self.root = MonteCarloNode.create_root() self.game_state = game_state else: self.game_state = None self.root = root self.data = TreeData()
def _reset_vis_data_internal(self, node: MonteCarloNode, depth=0): node.vis_details.x = -1 node.vis_details.y = depth node.vis_details.thread = None node.vis_details.mod = 0 node.vis_details._ancestor = self node.vis_details.change = 0 node.vis_details.shift = 0 node.left_most_sibling = None for child in node.children: self._reset_vis_data_internal(child, depth + 1)
def _first_walk(self, node: MonteCarloNode): if not node.has_children(): if node.leftmost_sibling(): node.vis_details.x = node.left_sibling( ).vis_details.x + self.distance else: node.vis_details.x = 0 else: default_ancestor = node.children[0] for child in node.children: self._first_walk(child) default_ancestor = self._apportion(child, default_ancestor) self._execute_shifts(node) midpoint = (node.children[0].vis_details.x + node.children[-1].vis_details.x) / 2 child = node.left_sibling() if child: node.vis_details.x = child.vis_details.x + self.distance node.vis_details.mod = node.vis_details.x - midpoint else: node.vis_details.x = midpoint return node
def get_child_with_max_score(node: MonteCarloNode): """ Returns child with biggest average prize. Exception is raised if node has no children. Args: node: MonteCarloNode object Returns: MonteCarloNode object, child with biggest average prize """ if not node.has_children(): raise Exception("Node does not have any child nodes") else: return max(node.children, key=lambda n: n.details.average_prize)
def _apportion(self, node: MonteCarloNode, default_ancestor): left_brother = node.left_sibling() if left_brother: v_in_right = v_out_right = node v_in_left = left_brother v_out_left = node.leftmost_sibling() sum_in_right = v_in_right.vis_details.mod sum_out_right = v_out_right.vis_details.mod sum_in_left = v_in_left.vis_details.mod sum_out_left = v_out_left.vis_details.mod while v_in_left.right() and v_in_right.left(): v_in_left = v_in_left.right() v_in_right = v_in_right.left() v_out_left = v_out_left.left() v_out_right = v_out_right.right() v_out_right._ancestor = node shift = (v_in_left.vis_details.x + sum_in_left) - ( v_in_right.vis_details.x + sum_in_right) + self.distance if shift > 0: ancestor = self._ancestor(v_in_left, node, default_ancestor) self._move_subtree(ancestor, node, shift) sum_in_right = sum_in_right + shift sum_out_right = sum_out_right + shift sum_in_left += v_in_left.vis_details.mod sum_in_right += v_in_right.vis_details.mod sum_out_left += v_out_left.vis_details.mod sum_out_right += v_out_right.vis_details.mod if v_in_left.right() and not v_out_right.right(): v_out_right.vis_details.thread = v_in_left.right() v_out_right.vis_details.mod += sum_in_left - sum_out_right elif v_in_right.left() and not v_out_left.left(): v_out_left.vis_details.thread = v_in_right.left() v_out_left.vis_details.mod += sum_in_right - sum_out_left if node.children: default_ancestor = node return default_ancestor
def get_random_child(node: MonteCarloNode): """ Returns random child of the node. Exception is raised if node has no children. Args: node: MonteCarloNode object Returns: MonteCarloNode object, random child of the given node """ if not node.has_children(): raise Exception("Node does not have any child nodes") else: child_index = RandomUtils.get_random_int(0, len(node.children)) return node.children[child_index]