class_docstr: This class implements the calculation of crowding distance for NSGA-II.
code: def accumulate_distance_per_objective(
      self, front: tp.List[p.Parameter], i: int
  ):
      if (
          isinstance(front[0].losses, np.ndarray)
          and front[0].losses.shape != ()
      ):
          is_multiobj: bool = (
              len(front[0].losses) > 1
          )  # isinstance(front[0].loss, np.ndarray)
      else:
          is_multiobj = False
      assert (not is_multiobj and (i == 0)) or is_multiobj
  
      # Sort the population by objective i
      if is_multiobj:
          front = sorted(front, key=lambda x: x.losses[i])
          objective_minn = front[0].losses[i]
          objective_maxn = front[-1].losses[i]
          assert objective_minn <= objective_maxn
  
          # Set the crowding distance
          front[0]._meta["crowding_distance"] = float("inf")
          front[-1]._meta["crowding_distance"] = float("inf")
  
          # All other intermediate solutions are assigned a distance value equal
          # to the absolute normalized difference in the function values of two
          # adjacent solutions.
          for j in range(1, len(front) - 1):
              distance = front[j + 1].losses[i] - front[j - 1].losses[i]
  
              # Check if minimum and maximum are the same (in which case do nothing)
              if objective_maxn - objective_minn == 0:
                  pass  # undefined
              else:
                  distance = distance / float(
                      objective_maxn - objective_minn
                  )
              logger.debug(
                  "front[j]: %s distance: %s", front[j].uid, distance
              )
              # The overall crowding-distance value is calculated as the sum of
              # individual distance values corresponding to each objective.
              front[j]._meta["crowding_distance"] += distance
      else:
          front = sorted(front, key=lambda x: x.loss)  # type: ignore
          objective_minn = front[0].loss
          objective_maxn = front[-1].loss
          assert objective_minn <= objective_maxn
  
          # Set the crowding distance
          front[0]._meta["crowding_distance"] = float("inf")
          front[-1]._meta["crowding_distance"] = float("inf")
  
          # All other intermediate solutions are assigned a distance value equal
          # to the absolute normalized difference in the function values of two
          # adjacent solutions.
          for j in range(1, len(front) - 1):
              if front[j + 1].loss is None or front[j - 1].loss is None:
                  distance = 0
              else:
                  distance = (
                      front[j + 1].loss
                      if front[j + 1].loss is not None
                      else 0
                  )
                  distance -= (
                      front[j - 1].loss
                      if front[j - 1].loss is not None
                      else 0
                  )
  
              # Check if minimum and maximum are the same (in which case do nothing)
              if objective_maxn - objective_minn == 0:
                  pass  # undefined
              else:
                  distance = distance / float(
                      objective_maxn - objective_minn
                  )
              # The overall crowding-distance value is calculated as the sum of
              # individual distance values corresponding to each objective.
              front[j]._meta["crowding_distance"] += distance
  
file_path: nevergrad/nevergrad/optimization/multiobjective/nsga2.py
imports: import logging
  import numpy
  import nevergrad.common.typing
  from nevergrad.parametrization import parameter
label_desc: Use image node_id 1 for calling the CrowdingDistance obj's underlying member method code with example usage: obj.accumulate_distance_per_objective(front, i) without return types