class_docstr: Mondrian Tree Regressor.
  
  Parameters
  ----------
  step
      Step of the tree.
  use_aggregation
      Whether to use aggregation weighting techniques or not.
  iteration
      Number iterations to do during training.
  seed
      Random seed for reproducibility.
  
  Notes
  -----
  The Mondrian Tree Regressor is a type of decision tree that bases splitting decisions over a
  Mondrian process.
  
  References
  ----------
  [^1]: Balaji Lakshminarayanan, Daniel M. Roy, Yee Whye Teh. Mondrian Forests: Efficient Online Random Forests.
      arXiv:1406.2673, pages 2-4.
class_docstr_tok: ["Mondrian","Tree","Regressor",".","Parameters","--","--","--","--","--","step","Step","of","the","tree",".","use_aggregation","Whether","to","use","aggregation","weighting","techniques","or","not",".","iteration","Number","iterations","to","do","during","training",".","seed","Random","seed","for","reproducibility",".","Notes","--","--","-","The","Mondrian","Tree","Regressor","is","a","type","of","decision","tree","that","bases","splitting","decisions","over","a","Mondrian","process",".","References","--","--","--","--","--","[","^1","]",":","Balaji","Lakshminarayanan",",","Daniel","M.","Roy",",","Yee","Whye","Teh",".","Mondrian","Forests",":","Efficient","Online","Random","Forests",".","arXiv:1406.2673",",","pages","2-4","."]
docstr: Update the tree (downward procedure).
docstr_tok: ["Update","the","tree","(","downward","procedure",")","."]
code: def _go_downwards(self):
      """Update the tree (downward procedure)."""
  
      # We update the nodes along the path which leads to the leaf containing the current
      # sample. For each node on the path, we consider the possibility of splitting it,
      # following the Mondrian process definition.
  
      # We start at the root
      current_node = self._root
  
      if self.iteration == 0:
          # If it's the first iteration, we just put the current sample in the range of root
          self._update_downwards(current_node, False)
          return current_node
      else:
          # Path from the parent to the current node
          branch_no = None
          while True:
              # Computing the extensions to get the intensities
              extensions_sum, extensions = current_node.range_extension(
                  self._x
              )
  
              # If it's not the first iteration (otherwise the current node
              # is root with no range), we consider the possibility of a split
              split_time = self._compute_split_time(
                  current_node, extensions_sum
              )
  
              if split_time > 0:
                  # We split the current node: because the current node is a
                  # leaf, or because we add a new node along the path
  
                  # We normalize the range extensions to get probabilities
                  intensities = utils.norm.normalize_values_in_dict(
                      extensions, inplace=False
                  )
  
                  # Sample the feature at random with a probability
                  # proportional to the range extensions
  
                  candidates = sorted(list(self._x.keys()))
                  feature = self._rng.choices(
                      candidates,
                      [intensities[c] for c in candidates],
                      k=1,
                  )[0]
  
                  x_f = self._x[feature]
  
                  # Is it a right extension of the node ?
                  range_min, range_max = current_node.range(feature)
                  is_right_extension = x_f > range_max
                  if is_right_extension:
                      threshold = self._rng.uniform(range_max, x_f)
                  else:
                      threshold = self._rng.uniform(x_f, range_min)
  
                  was_leaf = isinstance(
                      current_node, MondrianLeafRegressor
                  )
  
                  # We split the current node
                  current_node = self._split(
                      current_node,
                      split_time,
                      threshold,
                      feature,
                      is_right_extension,
                  )
  
                  # The root node has become a branch
                  if current_node.parent is None:
                      self._root = current_node
                  # Update path from the previous parent to the recently updated node
                  elif was_leaf:
                      parent = current_node.parent
                      if branch_no == 0:
                          parent.children = (
                              current_node,
                              parent.children[1],
                          )
                      else:
                          parent.children = (
                              parent.children[0],
                              current_node,
                          )
  
                  # Update the current node
                  self._update_downwards(current_node, True)
  
                  left, right = current_node.children
  
                  # Now, get the next node
                  if is_right_extension:
                      current_node = right
                  else:
                      current_node = left
  
                  # This is the leaf containing the sample point (we've just
                  # splitted the current node with the data point)
                  leaf = current_node
                  self._update_downwards(leaf, False)
                  return leaf
              else:
                  # There is no split, so we just update the node and go to the next one
                  self._update_downwards(current_node, True)
                  if isinstance(current_node, MondrianLeafRegressor):
                      return current_node
                  else:
                      # Save the path direction to keep the tree consistent
                      try:
                          branch_no = current_node.branch_no(self._x)
                          current_node = current_node.children[
                              branch_no
                          ]
                      except KeyError:  # Missing split feature
                          (
                              branch_no,
                              current_node,
                          ) = current_node.most_common_path()
  
file_path: river/river/tree/mondrian/mondrian_tree_regressor.py
imports: from __future__ import annotations
  import math
  from river import base, utils
  from river.tree.mondrian.mondrian_tree import MondrianTree
  from river.tree.mondrian.mondrian_tree_nodes import MondrianBranchRegressor, MondrianLeafRegressor, MondrianNodeRegressor
label_desc: Use image node_id 9 for calling the MondrianTreeRegressor obj's underlying member method code with example usage: obj._go_downwards() and returns: current_node, leaf, current_node