def __init__(self, tree_root, node_types=RFILL_NODE_TYPES, edge_types=RFILL_EDGE_TYPES, add_rev_edge=True):
    """Initializer.

    Args:
      tree_root: ProgNode type; the root of tree representation
      node_types: dict of nodetype to index
      edge_types: dict of edgetype to index
      add_rev_edge: whether add reversed edge
    """
    self.tree_root = tree_root
    self.add_rev_edge = add_rev_edge
    self.node_types = node_types
    self.edge_types = edge_types

    # list of tree nodes
    self.node_list = []

    # node feature index
    self.node_feats = []

    # list of (from_idx, to_idx, etype_int) tuples
    self.edge_list = []

    self.last_terminal = None  # used for linking terminals
    self.build_graph(self.tree_root)

    self.num_nodes = len(self.node_list)
    self.num_edges = len(self.edge_list)
    # unzipped version of edge list
    # self.from_list, self.to_list, self.edge_feats = \
    #     [np.array(x, dtype=np.int32) for x in zip(*self.edge_list)]

    self.node_feats = np.array(self.node_feats, dtype=np.int32)

    self.subexpr_ids = []
    for _, c in self.tree_root.children:
      self.subexpr_ids.append(c.index)