in nevergrad/optimization/multiobjective/hypervolume.py [0:0]
def recursive_hypervolume(self, dimension: int) -> float:
"""Recursive hypervolume computation. The algorithm is provided by Algorithm 3.
of the original paper."""
if self.multilist.chain_length(dimension - 1) == 0:
return 0
assert self.multilist is not None
if dimension == 0:
return -float(self.multilist.sentinel.next[0].coordinates[0])
if dimension == 1:
return self.plane_hypervolume()
# Line 4
for node in self.multilist.reverse_iterate(dimension):
assert node is not None
if node.dominated_flag < dimension:
node.dominated_flag = 0
# Line 5
hypervolume = 0.0
# Line 6
current_node = self.multilist.sentinel.prev[dimension]
# Lines 7 to 12
for node in self.multilist.reverse_iterate(dimension, start=current_node):
assert node is not None
current_node = node
if self.multilist.chain_length(dimension - 1) > 1 and (
node.coordinates[dimension] > self.reference_bounds[dimension]
or node.prev[dimension].coordinates[dimension] >= self.reference_bounds[dimension]
):
# Line 9
self.reference_bounds = self.multilist.update_coordinate_bounds(
self.reference_bounds, node, dimension
) # type: ignore
# Line 10
self.multilist.pop(node, dimension)
# Line 11
# front_size -= 1
else:
break
# Line 13
if self.multilist.chain_length(dimension - 1) > 1:
# Line 14
hypervolume = current_node.prev[dimension].volume[dimension]
hypervolume += current_node.prev[dimension].area[dimension] * (
current_node.coordinates[dimension] - current_node.prev[dimension].coordinates[dimension]
)
else:
current_node.configure_area(dimension)
# Line 15
current_node.volume[dimension] = hypervolume
# Line 16
self.skip_dominated_points(current_node, dimension)
# Line 17
for node in self.multilist.iterate(dimension, start=current_node.next[dimension]):
assert node is not None
# Line 18
hypervolume += node.prev[dimension].area[dimension] * (
node.coordinates[dimension] - node.prev[dimension].coordinates[dimension]
)
# Line 19
self.reference_bounds[dimension] = node.coordinates[dimension]
# Line 20
self.reference_bounds = self.multilist.update_coordinate_bounds(
self.reference_bounds, node, dimension
) # type: ignore
# Line 21
self.multilist.reinsert(node, dimension)
# Line 22
# front_size += 1
# Line 25
node.volume[dimension] = hypervolume
# Line 26
self.skip_dominated_points(node, dimension)
# Line 27
last_node = self.multilist.sentinel.prev[dimension]
hypervolume -= last_node.area[dimension] * last_node.coordinates[dimension]
return hypervolume