class_docstr: A GP class, inherited from Optimizer.
  
  This is the designed class to define GP-related
  variables and methods.
  
  References:
      J. Koza. Genetic programming: On the programming of computers by means of natural selection (1992).
docstr: Actually performs the crossover over a father and mother nodes.
  
  Args:
      father: A father's node to be crossed.
      mother: A mother's node to be crossed.
      max_father: Maximum of nodes from father to be used.
      max_mother: Maximum of nodes from mother to be used.
  
  Returns:
      (Tuple[Node, Node]): Two offsprings based on the crossover operator.
docstr_tok: ["Actually","performs","the","crossover","over","a","father","and","mother","nodes",".","Args",":","father",":","A","father","'s","node","to","be","crossed",".","mother",":","A","mother","'s","node","to","be","crossed",".","max_father",":","Maximum","of","nodes","from","father","to","be","used",".","max_mother",":","Maximum","of","nodes","from","mother","to","be","used",".","Returns",":","(","Tuple","[","Node",",","Node","]",")",":","Two","offsprings","based","on","the","crossover","operator","."]
code: def _cross(
      self, father: Node, mother: Node, max_father: int, max_mother: int
  ) -> Tuple[Node, Node]:
      """Actually performs the crossover over a father and mother nodes.
  
      Args:
          father: A father's node to be crossed.
          mother: A mother's node to be crossed.
          max_father: Maximum of nodes from father to be used.
          max_mother: Maximum of nodes from mother to be used.
  
      Returns:
          (Tuple[Node, Node]): Two offsprings based on the crossover operator.
  
      """
  
      father_offspring = copy.deepcopy(father)
      father_point = int(
          r.generate_uniform_random_number(2, max_father)
      )
  
      sub_father, flag_father = father_offspring.find_node(father_point)
  
      mother_offspring = copy.deepcopy(mother)
      mother_point = int(
          r.generate_uniform_random_number(2, max_mother)
      )
  
      sub_mother, flag_mother = mother_offspring.find_node(mother_point)
  
      if sub_father and sub_mother:
          # If father's node is positioned in the left
          if flag_father:
              branch = sub_father.left
  
              # If mother's node is positioned in the left
              if flag_mother:
                  sub_father.left = sub_mother.left
                  sub_mother.left.flag = True
              else:
                  sub_father.left = sub_mother.right
                  sub_mother.right.flag = True
          else:
              branch = sub_father.right
  
              # If mother's node is positioned in the left
              if flag_mother:
                  sub_father.right = sub_mother.left
                  sub_mother.left.flag = False
              else:
                  sub_father.right = sub_mother.right
                  sub_mother.right.flag = False
  
          sub_mother.parent = sub_father
  
          # Now, for creating the mother's offspring
          # Check if it is positioned in the left
          if flag_mother:
              sub_mother.left = branch
              branch.flag = True
          else:
              sub_mother.right = branch
              branch.flag = False
  
          branch.parent = sub_mother
  
      return father, mother
  
imports: import copy
  import time
  from typing import Any, Dict, Optional, Tuple
  import numpy
  import opytimizer.math.general
  import opytimizer.math.random
  import opytimizer.utils.exception
  from opytimizer.core import Optimizer
  from opytimizer.core.function import Function
  from opytimizer.core.node import Node
  from opytimizer.core.space import Space
  from opytimizer.spaces.tree import TreeSpace
  from opytimizer.utils import logging
label_desc: Use image node_id 15 for calling the GP obj's underlying member method code with example usage: obj._cross(father, mother, max_father, max_mother) and returns: father,  mother