class_docstr: Unimodal Normal Distribution Crossover used by :class:`~optuna.samplers.NSGAIISampler`.
  
  Generates child individuals from the three parents
  using a multivariate normal distribution.
  
  - `H. Kita, I. Ono and S. Kobayashi,
    Multi-parental extension of the unimodal normal distribution crossover
    for real-coded genetic algorithms,
    Proceedings of the 1999 Congress on Evolutionary Computation-CEC99
    (Cat. No. 99TH8406), 1999, pp. 1581-1588 Vol. 2
    <https://ieeexplore.ieee.org/document/782672>`_
  
  Args:
      sigma_xi:
          Parametrizes normal distribution from which ``xi`` is drawn.
      sigma_eta:
          Parametrizes normal distribution from which ``etas`` are drawn.
          If not specified, defaults to ``0.35 / sqrt(len(search_space))``.
code: def crossover(
      self,
      parents_params: np.ndarray,
      rng: np.random.RandomState,
      study: Study,
      search_space_bounds: np.ndarray,
  ) -> np.ndarray:
      # https://ieeexplore.ieee.org/document/782672
      # Section 2 Unimodal Normal Distribution Crossover
      n = len(search_space_bounds)
      xp = (parents_params[0] + parents_params[1]) / 2  # Section 2 (2).
      d = parents_params[0] - parents_params[1]  # Section 2 (3).
      if self._sigma_eta is None:
          sigma_eta = 0.35 / np.sqrt(n)
      else:
          sigma_eta = self._sigma_eta
  
      etas = rng.normal(0, sigma_eta**2, size=n)
      xi = rng.normal(0, self._sigma_xi**2)
      es = self._orthonormal_basis_vector_to_psl(
          parents_params, n
      )  # Orthonormal basis vectors of the subspace orthogonal to the psl.
      one = xp  # Section 2 (5).
      two = xi * d  # Section 2 (5).
  
      if n > 1:  # When n=1, there is no subsearch component.
          three = np.zeros(n)  # Section 2 (5).
          D = self._distance_from_x_to_psl(
              parents_params
          )  # Section 2 (4).
          for i in range(n - 1):
              three += etas[i] * es[i]
          three *= D
          child_params = one + two + three
  
      else:
          child_params = one + two
  
      return child_params
  
file_path: optuna/optuna/samplers/nsgaii/_crossovers/_undx.py
imports: from typing import Optional
  import numpy
  from optuna._experimental import experimental_class
  from optuna.samplers.nsgaii._crossovers._base import BaseCrossover
  from optuna.study import Study
label_desc: Use image node_id 4 for calling the UNDXCrossover obj's underlying member method code with example usage: obj.crossover(parents_params, rng, study, search_space_bounds) and returns: child_params