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