class_docstr: Tree node data structure
  
  Nodes have an attribute item to carry arbitrary information. A node may only have one parent
  and can have as many children as desired.
  
  Parents can be set at initialization or via `node.set_parent`. Setting a parent automatically
  set the current node as the child of the parent.
  
  Children can be set at initialization or via `node.add_children`. Setting children
  automatically set their parent as the current node.
  
  Tree of nodes are iterable, by default with preorder traversal.
  
  .. seealso::
      `orion.core.utils.tree.PreOrderTraversal`
      `orion.core.utils.tree.DepthFirstTraversal`
  
  Attributes
  ----------
  item: T
      Can be anything
  parent: None or instance of `orion.core.utils.tree.TreeNode`
      The parent of the current node, None if the current node is the root.
  children: None or list of instances of `orion.core.utils.tree.TreeNode`
      The children of the current node.
  root: instance of `orion.core.utils.tree.TreeNode`
      The top node of the current tree. The root node returns itself.
  
  Examples
  --------
  .. code-block:: python
      :linenos:
  
      a = TreeNode("a")
      b = TreeNode("b", a)
      c = TreeNode("c", a)
      d = TreeNode("d", a)
      e = TreeNode("e", a)
  
      f = TreeNode("f", b)
      g = TreeNode("g", b)
  
      h = TreeNode("h", e)
  
      # Gives this tree
      # a
      # |   \  \   \
      # b    c  d   e
      # | \         |
      # f  g        h
  
      g.set_parent(e)
  
      # Gives this tree
      # a
      # |  \  \   \
      # b   c  d   e
      # |          | \
      # f          h g
  
      c.add_children(h, g)
  
      # Gives this tree
      # a
      # |  \    \   \
      # b   c    d   e
      # |   | \
      # f   h  g
  
      a.drop_children(c)
  
      # Gives this tree
      # a
      # |  \   \
      # b   d   e
      # |
      # f
class_docstr_tok: ["Tree","node","data","structure","Nodes","have","an","attribute","item","to","carry","arbitrary","information",".","A","node","may","only","have","one","parent","and","can","have","as","many","children","as","desired",".","Parents","can","be","set","at","initialization","or","via","`","node.set_parent","`",".","Setting","a","parent","automatically","set","the","current","node","as","the","child","of","the","parent",".","Children","can","be","set","at","initialization","or","via","`","node.add_children","`",".","Setting","children","automatically","set","their","parent","as","the","current","node",".","Tree","of","nodes","are","iterable",",","by","default","with","preorder","traversal",".","..","seealso",":",":","`","orion.core.utils.tree.PreOrderTraversal","`","`","orion.core.utils.tree.DepthFirstTraversal","`","Attributes","--","--","--","--","--","item",":","T","Can","be","anything","parent",":","None","or","instance","of","`","orion.core.utils.tree.TreeNode","`","The","parent","of","the","current","node",",","None","if","the","current","node","is","the","root",".","children",":","None","or","list","of","instances","of","`","orion.core.utils.tree.TreeNode","`","The","children","of","the","current","node",".","root",":","instance","of","`","orion.core.utils.tree.TreeNode","`","The","top","node","of","the","current","tree",".","The","root","node","returns","itself",".","Examples","--","--","--","--","..","code-block",":",":","python",":","linenos",":","a","=","TreeNode","(","``","a","''",")","b","=","TreeNode","(","``","b","''",",","a",")","c","=","TreeNode","(","``","c","''",",","a",")","d","=","TreeNode","(","``","d","''",",","a",")","e","=","TreeNode","(","``","e","''",",","a",")","f","=","TreeNode","(","``","f","''",",","b",")","g","=","TreeNode","(","``","g","''",",","b",")","h","=","TreeNode","(","``","h","''",",","e",")","#","Gives","this","tree","#","a","#","|","\\","\\","\\","#","b","c","d","e","#","|","\\","|","#","f","g","h","g.set_parent","(","e",")","#","Gives","this","tree","#","a","#","|","\\","\\","\\","#","b","c","d","e","#","|","|","\\","#","f","h","g","c.add_children","(","h",",","g",")","#","Gives","this","tree","#","a","#","|","\\","\\","\\","#","b","c","d","e","#","|","|","\\","#","f","h","g","a.drop_children","(","c",")","#","Gives","this","tree","#","a","#","|","\\","\\","#","b","d","e","#","|","#","f"]
docstr: Apply a function recursively on the tree
  
  The function can be applied upwards on parents or downwards on children. The direction is
  defined by passing self.parent or self.children as the node argument.
  
  Parameters
  ----------
  function : callable
      Callable object to which will be passed the current node plus the parent node or the
      children nodes, depending on the direction of function application.
      If map on parents, callable(self, rval_parent_node)
      If map on children, callable(self, rval_children_nodes).
      Note that the callable object is expected to return an object which will be set as the
      current node's item (in the resulting tree), and the parent node or the children nodes
      depending on the direction of function application.
  node: None, `orion.core.evc.TreeNode` or list
      Can be either
      `None`: function is applied on current node only
      `self.parent`: function is applied recursively climbing up the tree until the root
      `self.children`: function is applied recursively going down the tree until the leafs
  
  Examples
  --------
  .. code-block:: python
      :linenos:
  
      # Tree structure
      # a
      # |   \  \   \
      # b    c  d   e
      # | \         |
      # f  g        h
      #
  
      root = TreeNode(1)
      b = TreeNode(1, root)
      TreeNode(1, root)
      TreeNode(1, root)
      e = TreeNode(1, root)
  
      f = TreeNode(1, b)
      TreeNode(1, b)
  
      h = TreeNode(1, e)
  
      def increment(node, children):
          for child in TreeNode(0, None, children):
              child.item += 1
  
          return node.item + 1, children
  
      # Should return
      #
      # 2
      # |   \  \   \
      # 3    3  3   3
      # | \         |
      # 4  4        4
  
      rval = root.map(increment, root.children)
      assert [node.item for node in rval] == [2, 3, 4, 4, 3, 3, 3, 4]
  
      def increment_parent(node, parent):
          if parent is not None:
              for parent in parent.root:
                  parent.item += 1
  
          return node.item + 1, parent
  
      # Should return
      #
      # 4
      # |
      # 3
      # |
      # 2
  
      rval = f.map(increment_parent, f.parent)
      assert [node.item for node in rval.root] == [4, 3, 2]
  
      rval = h.map(increment_parent, h.parent)
      assert [node.item for node in rval.root] == [4, 3, 2]
docstr_tok: ["Apply","a","function","recursively","on","the","tree","The","function","can","be","applied","upwards","on","parents","or","downwards","on","children",".","The","direction","is","defined","by","passing","self.parent","or","self.children","as","the","node","argument",".","Parameters","--","--","--","--","--","function",":","callable","Callable","object","to","which","will","be","passed","the","current","node","plus","the","parent","node","or","the","children","nodes",",","depending","on","the","direction","of","function","application",".","If","map","on","parents",",","callable","(","self",",","rval_parent_node",")","If","map","on","children",",","callable","(","self",",","rval_children_nodes",")",".","Note","that","the","callable","object","is","expected","to","return","an","object","which","will","be","set","as","the","current","node","'s","item","(","in","the","resulting","tree",")",",","and","the","parent","node","or","the","children","nodes","depending","on","the","direction","of","function","application",".","node",":","None",",","`","orion.core.evc.TreeNode","`","or","list","Can","be","either","`","None","`",":","function","is","applied","on","current","node","only","`","self.parent","`",":","function","is","applied","recursively","climbing","up","the","tree","until","the","root","`","self.children","`",":","function","is","applied","recursively","going","down","the","tree","until","the","leafs","Examples","--","--","--","--","..","code-block",":",":","python",":","linenos",":","#","Tree","structure","#","a","#","|","\\","\\","\\","#","b","c","d","e","#","|","\\","|","#","f","g","h","#","root","=","TreeNode","(","1",")","b","=","TreeNode","(","1",",","root",")","TreeNode","(","1",",","root",")","TreeNode","(","1",",","root",")","e","=","TreeNode","(","1",",","root",")","f","=","TreeNode","(","1",",","b",")","TreeNode","(","1",",","b",")","h","=","TreeNode","(","1",",","e",")","def","increment","(","node",",","children",")",":","for","child","in","TreeNode","(","0",",","None",",","children",")",":","child.item","+=","1","return","node.item","+","1",",","children","#","Should","return","#","#","2","#","|","\\","\\","\\","#","3","3","3","3","#","|","\\","|","#","4","4","4","rval","=","root.map","(","increment",",","root.children",")","assert","[","node.item","for","node","in","rval","]","==","[","2",",","3",",","4",",","4",",","3",",","3",",","3",",","4","]","def","increment_parent","(","node",",","parent",")",":","if","parent","is","not","None",":","for","parent","in","parent.root",":","parent.item","+=","1","return","node.item","+","1",",","parent","#","Should","return","#","#","4","#","|","#","3","#","|","#","2","rval","=","f.map","(","increment_parent",",","f.parent",")","assert","[","node.item","for","node","in","rval.root","]","==","[","4",",","3",",","2","]","rval","=","h.map","(","increment_parent",",","h.parent",")","assert","[","node.item","for","node","in","rval.root","]","==","[","4",",","3",",","2","]"]
code: def map(
      self,
      function: Callable,
      node: TreeNode[T] | Sequence[TreeNode[T]] | None,
  ) -> TreeNode:
      r"""Apply a function recursively on the tree
  
          The function can be applied upwards on parents or downwards on children. The direction is
          defined by passing self.parent or self.children as the node argument.
  
          Parameters
          ----------
          function : callable
              Callable object to which will be passed the current node plus the parent node or the
              children nodes, depending on the direction of function application.
              If map on parents, callable(self, rval_parent_node)
              If map on children, callable(self, rval_children_nodes).
              Note that the callable object is expected to return an object which will be set as the
              current node's item (in the resulting tree), and the parent node or the children nodes
              depending on the direction of function application.
          node: None, `orion.core.evc.TreeNode` or list
              Can be either
              `None`: function is applied on current node only
              `self.parent`: function is applied recursively climbing up the tree until the root
              `self.children`: function is applied recursively going down the tree until the leafs
  
          Examples
          --------
          .. code-block:: python
              :linenos:
  
              # Tree structure
              # a
              # |   \  \   \
              # b    c  d   e
              # | \         |
              # f  g        h
              #
  
              root = TreeNode(1)
              b = TreeNode(1, root)
              TreeNode(1, root)
              TreeNode(1, root)
              e = TreeNode(1, root)
  
              f = TreeNode(1, b)
              TreeNode(1, b)
  
              h = TreeNode(1, e)
  
              def increment(node, children):
                  for child in TreeNode(0, None, children):
                      child.item += 1
  
                  return node.item + 1, children
  
              # Should return
              #
              # 2
              # |   \  \   \
              # 3    3  3   3
              # | \         |
              # 4  4        4
  
              rval = root.map(increment, root.children)
              assert [node.item for node in rval] == [2, 3, 4, 4, 3, 3, 3, 4]
  
              def increment_parent(node, parent):
                  if parent is not None:
                      for parent in parent.root:
                          parent.item += 1
  
                  return node.item + 1, parent
  
              # Should return
              #
              # 4
              # |
              # 3
              # |
              # 2
  
              rval = f.map(increment_parent, f.parent)
              assert [node.item for node in rval.root] == [4, 3, 2]
  
              rval = h.map(increment_parent, h.parent)
              assert [node.item for node in rval.root] == [4, 3, 2]
  
          """
      if node is None:
          rval, _ = function(self, None)
          return TreeNode(rval)
      elif node is self.parent:
          assert node is not None
          assert isinstance(node, TreeNode)
          rval_parent_node = node.map(function, node.parent)
          rval, parent_node = function(self, rval_parent_node)
          return TreeNode(rval, parent_node)
      elif node is self.children:
          rval_children_nodes = [
              child.map(function, child.children)
              for child in self.children
          ]
          rval, children_nodes = function(self, rval_children_nodes)
          return TreeNode(rval, parent=None, children=children_nodes)
      else:
          raise ValueError(f"Invalid nodes: {str(node)}")
  
imports: from __future__ import annotations
  from typing import Callable, Generic, Iterable, Iterator, Sequence, TypeVar
label_desc: Use image node_id 14 for calling the TreeNode obj's underlying member method code with example usage: obj.map(function, node) and returns: TreeNode, TreeNode, TreeNode