Skip to content

Commit 44bb2d3

Browse files
Merge pull request optuna#6115 from shmurai/perf-hypervolume_history_info
Improve performance of `plot_hypervolume_history`
2 parents a30812e + 87cf1a2 commit 44bb2d3

File tree

1 file changed

+25
-24
lines changed

1 file changed

+25
-24
lines changed

optuna/visualization/_hypervolume_history.py

Lines changed: 25 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,7 @@
1010
from optuna.logging import get_logger
1111
from optuna.samplers._base import _CONSTRAINTS_KEY
1212
from optuna.study import Study
13-
from optuna.study._multi_objective import _dominates
1413
from optuna.study._study_direction import StudyDirection
15-
from optuna.trial import FrozenTrial
1614
from optuna.trial import TrialState
1715
from optuna.visualization._plotly_imports import _imports
1816

@@ -98,8 +96,8 @@ def _get_hypervolume_history_info(
9896

9997
# Only feasible trials are considered in hypervolume computation.
10098
trial_numbers = []
101-
values = []
102-
best_trials: list[FrozenTrial] = []
99+
hypervolume_values = []
100+
best_trials_values_normalized: np.ndarray | None = None
103101
hypervolume = 0.0
104102
for trial in completed_trials:
105103
trial_numbers.append(trial.number)
@@ -109,31 +107,34 @@ def _get_hypervolume_history_info(
109107
constraints_values = trial.system_attrs[_CONSTRAINTS_KEY]
110108
if any(map(lambda x: x > 0.0, constraints_values)):
111109
# The trial is infeasible.
112-
values.append(hypervolume)
110+
hypervolume_values.append(hypervolume)
113111
continue
114112

115-
if any(map(lambda t: _dominates(t, trial, study.directions), best_trials)):
116-
# The trial is not on the Pareto front.
117-
values.append(hypervolume)
118-
continue
119-
120-
best_trials = list(
121-
filter(lambda t: not _dominates(trial, t, study.directions), best_trials)
122-
) + [trial]
123-
124-
loss_vals = np.asarray(
125-
list(
126-
filter(
127-
lambda v: (v <= minimization_reference_point).all(),
128-
[signs * trial.values for trial in best_trials],
129-
)
113+
values_normalized = (signs * trial.values)[np.newaxis, :]
114+
if best_trials_values_normalized is not None:
115+
if (best_trials_values_normalized <= values_normalized).all(axis=1).any(axis=0):
116+
# The trial is not on the Pareto front.
117+
hypervolume_values.append(hypervolume)
118+
continue
119+
120+
if best_trials_values_normalized is None:
121+
best_trials_values_normalized = values_normalized
122+
else:
123+
is_kept = (best_trials_values_normalized < values_normalized).any(axis=1)
124+
best_trials_values_normalized = np.concatenate(
125+
[best_trials_values_normalized[is_kept, :], values_normalized], axis=0
130126
)
131-
)
127+
128+
loss_vals = best_trials_values_normalized[
129+
(best_trials_values_normalized <= minimization_reference_point[np.newaxis, :]).all(
130+
axis=1
131+
)
132+
]
132133
if loss_vals.size > 0:
133134
hypervolume = compute_hypervolume(loss_vals, minimization_reference_point)
134-
values.append(hypervolume)
135+
hypervolume_values.append(hypervolume)
135136

136-
if len(best_trials) == 0:
137+
if best_trials_values_normalized is None:
137138
_logger.warning("Your study does not have any feasible trials.")
138139

139-
return _HypervolumeHistoryInfo(trial_numbers, values)
140+
return _HypervolumeHistoryInfo(trial_numbers, hypervolume_values)

0 commit comments

Comments
 (0)