Skip to content

Commit

Permalink
Merge pull request optuna#5687 from nabenabe0928/doc/add-more-informa…
Browse files Browse the repository at this point in the history
…tion-of-hack-in-wfg

Add more information about the hack in `WFG`
  • Loading branch information
not522 authored Oct 4, 2024
2 parents 71914f3 + 79baaec commit 0585c35
Showing 1 changed file with 32 additions and 3 deletions.
35 changes: 32 additions & 3 deletions optuna/_hypervolume/wfg.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,34 @@ def _compute_exclusive_hv(
if limited_sols.shape[0] == 0:
return inclusive_hv

# NOTE(nabenabe): For hypervolume calculation, duplicated Pareto solutions can be ignored. As
# limited_sols[:, 0] is sorted, all the Pareto solutions necessary for hypervolume calculation
# will be eliminated with assume_unique_lexsorted=True.
# NOTE(nabenabe): As the following line is a hack for speedup, I will describe several
# important points to note. Even if we do not run _is_pareto_front below or use
# assume_unique_lexsorted=False instead, the result of this function does not change, but this
# function simply becomes slower.
#
# For simplicity, I call an array ``quasi-lexsorted`` if it is sorted by the first objective.
#
# Reason why it will be faster with _is_pareto_front
# Hypervolume of a given solution set and a reference point does not change even when we
# remove non Pareto solutions from the solution set. However, the calculation becomes slower
# if the solution set contains many non Pareto solutions. By removing some obvious non Pareto
# solutions, the calculation becomes faster.
#
# Reason why assume_unique_lexsorted must be True for _is_pareto_front
# assume_unique_lexsorted=True actually checks weak dominance and solutions will be weakly
# dominated if there are duplications, so we can remove duplicated solutions by this option.
# In other words, assume_unique_lexsorted=False may significantly slow down when limited_sols
# has many duplicated Pareto solutions because this function becomes an exponential algorithm
# without duplication removal.
#
# NOTE(nabenabe): limited_sols can be non-unique and/or non-lexsorted, so I will describe why
# it is fine.
#
# Reason why we can specify assume_unique_lexsorted=True even when limited_sols is not
# All ``False`` in on_front will be correct (, but it may not be the case for ``True``) even
# if limited_sols is not unique or not lexsorted as long as limited_sols is quasi-lexsorted,
# which is guaranteed. As mentioned earlier, if all ``False`` in on_front is correct, the
# result of this function does not change.
on_front = _is_pareto_front(limited_sols, assume_unique_lexsorted=True)
return inclusive_hv - _compute_hv(limited_sols[on_front], reference_point)

Expand Down Expand Up @@ -92,6 +117,10 @@ def compute_hypervolume(
on_front = _is_pareto_front(unique_lexsorted_loss_vals, assume_unique_lexsorted=True)
sorted_pareto_sols = unique_lexsorted_loss_vals[on_front]
else:
# NOTE(nabenabe): The result of this function does not change both by
# np.argsort(loss_vals[:, 0]) and np.unique(loss_vals, axis=0).
# But many duplications in loss_vals significantly slows down the function.
# TODO(nabenabe): Make an option to use np.unique.
sorted_pareto_sols = loss_vals[loss_vals[:, 0].argsort()]

if reference_point.shape[0] == 2:
Expand Down

0 comments on commit 0585c35

Please sign in to comment.