def accumulate_distance_per_objective()

in nevergrad/optimization/multiobjective/nsga2.py [0:0]


    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