class_docstr: A sum tree data structure for storing replay priorities.
  
  A sum tree is a complete binary tree whose leaves contain values called
  priorities. Internal nodes maintain the sum of the priorities of all leaf
  nodes in their subtree.
  
  For capacity = 4, the tree may look like this:
  
               +---+
               |2.5|
               +-+-+
                 |
         +-------+--------+
         |                |
       +-+-+            +-+-+
       |1.5|            |1.0|
       +-+-+            +-+-+
         |                |
    +----+----+      +----+----+
    |         |      |         |
  +-+-+     +-+-+  +-+-+     +-+-+
  |0.5|     |1.0|  |0.5|     |0.5|
  +---+     +---+  +---+     +---+
  
  This is stored in a list of numpy arrays:
  self.nodes = [ [2.5], [1.5, 1], [0.5, 1, 0.5, 0.5] ]
  
  For conciseness, we allocate arrays as powers of two, and pad the excess
  elements with zero values.
  
  This is similar to the usual array-based representation of a complete binary
  tree, but is a little more user-friendly.
docstr: Samples an element from the sum tree.
  
  Each element has probability p_i / sum_j p_j of being picked, where p_i is
  the (positive) value associated with node i (possibly unnormalized).
  
  Args:
    query_value: float in [0, 1], used as the random value to select a
    sample. If None, will select one randomly in [0, 1).
  
  Returns:
    int, a random element from the sum tree.
  
  Raises:
    Exception: If the sum tree is empty (i.e. its node values sum to 0), or if
      the supplied query_value is larger than the total sum.
docstr_tok: ["Samples","an","element","from","the","sum","tree",".","Each","element","has","probability","p_i","\/","sum_j","p_j","of","being","picked",",","where","p_i","is","the","(","positive",")","value","associated","with","node","i","(","possibly","unnormalized",")",".","Args",":","query_value",":","float","in","[","0",",","1","]",",","used","as","the","random","value","to","select","a","sample",".","If","None",",","will","select","one","randomly","in","[","0",",","1",")",".","Returns",":","int",",","a","random","element","from","the","sum","tree",".","Raises",":","Exception",":","If","the","sum","tree","is","empty","(","i.e",".","its","node","values","sum","to","0",")",",","or","if","the","supplied","query_value","is","larger","than","the","total","sum","."]
code: def sample(self, query_value=None):
      """Samples an element from the sum tree.
  
      Each element has probability p_i / sum_j p_j of being picked, where p_i is
      the (positive) value associated with node i (possibly unnormalized).
  
      Args:
        query_value: float in [0, 1], used as the random value to select a
        sample. If None, will select one randomly in [0, 1).
  
      Returns:
        int, a random element from the sum tree.
  
      Raises:
        Exception: If the sum tree is empty (i.e. its node values sum to 0), or if
          the supplied query_value is larger than the total sum.
      """
      if self._total_priority() == 0.0:
          raise Exception("Cannot sample from an empty sum tree.")
  
      if query_value and (query_value < 0.0 or query_value > 1.0):
          raise ValueError("query_value must be in [0, 1].")
  
      # Sample a value in range [0, R), where R is the value stored at the root.
      query_value = (
          random.random() if query_value is None else query_value
      )
      query_value *= self._total_priority()
  
      # Now traverse the sum tree.
      node_index = 0
      for nodes_at_this_depth in self.nodes[1:]:
          # Compute children of previous depth's node.
          left_child = node_index * 2
  
          left_sum = nodes_at_this_depth[left_child]
          # Each subtree describes a range [0, a), where a is its value.
          if query_value < left_sum:  # Recurse into left subtree.
              node_index = left_child
          else:  # Recurse into right subtree.
              node_index = left_child + 1
              # Adjust query to be relative to right subtree.
              query_value -= left_sum
  
      return node_index
  
file_path: dopamine/dopamine/replay_memory/sum_tree.py
imports: from __future__ import absolute_import
  from __future__ import division
  from __future__ import print_function
  import math
  import random
  import numpy
label_desc: Use image node_id 3 for calling the SumTree obj's underlying member method code with example usage: obj.sample(query_value) and returns: node_index