1010from optuna .logging import get_logger
1111from optuna .samplers ._base import _CONSTRAINTS_KEY
1212from optuna .study import Study
13- from optuna .study ._multi_objective import _dominates
1413from optuna .study ._study_direction import StudyDirection
15- from optuna .trial import FrozenTrial
1614from optuna .trial import TrialState
1715from 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