code: def _associate_individuals_with_reference_points(
      objective_matrix: np.ndarray, reference_points: np.ndarray
  ) -> tuple[np.ndarray, np.ndarray]:
      """Associates each objective value to the closest reference point.
  
      Associate each normalized objective value to the closest reference point. The distance is
      calculated by Euclidean norm.
  
      Args:
          objective_matrix:
              A 2 dimension ``numpy.ndarray`` with columns of objective dimension and rows of
              generation size. Each row is the normalized objective value of the corresponding
              individual.
  
      Returns:
          closest_reference_points:
              A ``numpy.ndarray`` with rows of generation size. Each row is the index of
              the closest reference point to the corresponding individual.
          distance_reference_points:
              A ``numpy.ndarray`` with rows of generation size. Each row is the distance from
              the corresponding individual to the closest reference point.
      """
      # TODO(Shinichi) Implement faster assignment for the default reference points because it does
      # not seem necessary to calculate distance from all reference points.
  
      # TODO(Shinichi) Normalize reference_points in constructor to remove reference_point_norms.
      # In addition, the minimum distance from each reference point can be replaced with maximum
      # inner product between the given individual and each normalized reference points.
  
      # distance_from_reference_lines is a ndarray of shape (n, p), where n is the size of the
      # population and p is the number of reference points. Its (i,j) entry keeps distance between
      # the i-th individual values and the j-th reference line.
      reference_point_norm_squared = (
          np.linalg.norm(reference_points, axis=1) ** 2
      )
      perpendicular_vectors_to_reference_lines = np.einsum(
          "ni,pi,p,pm->npm",
          objective_matrix,
          reference_points,
          1 / reference_point_norm_squared,
          reference_points,
      )
      distance_from_reference_lines = np.linalg.norm(
          objective_matrix[:, np.newaxis, :]
          - perpendicular_vectors_to_reference_lines,
          axis=2,
      )
      closest_reference_points: np.ndarray = np.argmin(
          distance_from_reference_lines, axis=1
      )
      distance_reference_points: np.ndarray = np.min(
          distance_from_reference_lines, axis=1
      )
  
      return closest_reference_points, distance_reference_points
  
imports: from __future__ import annotations
  from collections import defaultdict
  from collections.abc import Callable
  from collections.abc import Sequence
  import itertools
  import math
  import numpy
  from optuna.samplers._lazy_random_state import LazyRandomState
  from optuna.samplers.nsgaii._dominates import _constrained_dominates
  from optuna.samplers.nsgaii._dominates import _validate_constraints
  from optuna.samplers.nsgaii._elite_population_selection_strategy import _fast_non_dominated_sort
  from optuna.study import Study
  from optuna.study._multi_objective import _dominates
  from optuna.trial import FrozenTrial
label_desc: Use image node_id 5 for calling a global function with example usage: _associate_individuals_with_reference_points(objective_matrix, reference_points) and returns: closest_reference_points,  distance_reference_points