99from __future__ import annotations
1010
1111import warnings
12- from collections .abc import Callable , Iterable , Mapping , MutableMapping , Sequence
12+ from collections .abc import Iterable , Mapping , MutableMapping , Sequence
1313from copy import deepcopy
1414from logging import Logger
15- from typing import Any , cast , SupportsFloat , TYPE_CHECKING
15+ from typing import Any , Callable , cast , SupportsFloat , TYPE_CHECKING
1616
1717import numpy as np
1818import numpy .typing as npt
@@ -206,7 +206,7 @@ def extract_objective_thresholds(
206206 objective_thresholds : TRefPoint ,
207207 objective : Objective ,
208208 outcomes : list [str ],
209- experiment : Experiment ,
209+ metric_name_to_signature : Mapping [ str , str ] ,
210210) -> npt .NDArray | None :
211211 """Extracts objective thresholds' values, in the order of `outcomes`.
212212
@@ -222,7 +222,7 @@ def extract_objective_thresholds(
222222 objective_thresholds: Objective thresholds to extract values from.
223223 objective: The corresponding Objective, for validation purposes.
224224 outcomes: n-length list of names of metrics.
225- experiment: The experiment, used to map metric names to signatures.
225+ metric_name_to_signature: Mapping from metric names to signatures.
226226
227227 Returns:
228228 (n,) array of thresholds
@@ -232,7 +232,7 @@ def extract_objective_thresholds(
232232
233233 objective_threshold_dict = {}
234234 for ot in objective_thresholds :
235- ot_signature = experiment . get_metric ( ot .metric_names [0 ]). signature
235+ ot_signature = metric_name_to_signature [ ot .metric_names [0 ]]
236236 if ot .relative :
237237 raise ValueError (
238238 f"Objective { ot_signature } has a relative threshold that "
@@ -242,7 +242,7 @@ def extract_objective_thresholds(
242242
243243 # Check that all thresholds correspond to a metric.
244244 obj_metric_signatures = [
245- experiment . get_metric ( name ). signature for name in objective .metric_names
245+ metric_name_to_signature [ name ] for name in objective .metric_names
246246 ]
247247 if set (objective_threshold_dict .keys ()).difference (set (obj_metric_signatures )):
248248 raise ValueError (
@@ -259,7 +259,9 @@ def extract_objective_thresholds(
259259
260260
261261def extract_objective_weights (
262- objective : Objective , outcomes : list [str ], experiment : Experiment
262+ objective : Objective ,
263+ outcomes : list [str ],
264+ metric_name_to_signature : Mapping [str , str ],
263265) -> npt .NDArray :
264266 """Extract a weights for objectives.
265267
@@ -277,7 +279,7 @@ def extract_objective_weights(
277279 Args:
278280 objective: Objective to extract weights from.
279281 outcomes: n-length list of metric signatures.
280- experiment: The experiment, used to map metric names to signatures.
282+ metric_name_to_signature: Mapping from metric names to signatures.
281283
282284 Returns:
283285 n-length array of weights.
@@ -287,13 +289,15 @@ def extract_objective_weights(
287289 # metric_weights returns sign-encoded (name, weight) tuples for all
288290 # objective types (single, scalarized, multi).
289291 for obj_metric_name , obj_weight in objective .metric_weights :
290- sig = experiment . get_metric ( obj_metric_name ). signature
292+ sig = metric_name_to_signature [ obj_metric_name ]
291293 objective_weights [outcomes .index (sig )] = obj_weight
292294 return objective_weights
293295
294296
295297def extract_objective_weight_matrix (
296- objective : Objective , outcomes : list [str ], experiment : Experiment
298+ objective : Objective ,
299+ outcomes : list [str ],
300+ metric_name_to_signature : Mapping [str , str ],
297301) -> npt .NDArray :
298302 """Extract a 2D weight matrix for objectives.
299303
@@ -308,6 +312,7 @@ def extract_objective_weight_matrix(
308312 Args:
309313 objective: Objective to extract weights from.
310314 outcomes: n-length list of signatures of metrics.
315+ metric_name_to_signature: Mapping from metric names to signatures.
311316
312317 Returns:
313318 ``(n_objectives, n)`` array of weights.
@@ -319,19 +324,23 @@ def extract_objective_weight_matrix(
319324 extract_objective_weights (
320325 objective = Objective (expression = f"{ weight } * { name } " ),
321326 outcomes = outcomes ,
322- experiment = experiment ,
327+ metric_name_to_signature = metric_name_to_signature ,
323328 )
324329 )
325330 return np .stack (rows , axis = 0 )
326331 else :
327332 # Single row – covers Objective and ScalarizedObjective
328- return extract_objective_weights (objective , outcomes , experiment ).reshape (1 , - 1 )
333+ return extract_objective_weights (
334+ objective = objective ,
335+ outcomes = outcomes ,
336+ metric_name_to_signature = metric_name_to_signature ,
337+ ).reshape (1 , - 1 )
329338
330339
331340def extract_outcome_constraints (
332341 outcome_constraints : list [OutcomeConstraint ],
333342 outcomes : list [str ],
334- experiment : Experiment ,
343+ metric_name_to_signature : Mapping [ str , str ] ,
335344) -> TBounds :
336345 if len (outcome_constraints ) == 0 :
337346 return None
@@ -342,10 +351,10 @@ def extract_outcome_constraints(
342351 s = 1 if c .op == ComparisonOp .LEQ else - 1
343352 if isinstance (c , ScalarizedOutcomeConstraint ):
344353 for c_metric_name , c_weight in c .metric_weights :
345- j = outcomes .index (experiment . get_metric ( c_metric_name ). signature )
354+ j = outcomes .index (metric_name_to_signature [ c_metric_name ] )
346355 A [i , j ] = s * c_weight
347356 else :
348- j = outcomes .index (experiment . get_metric ( c .metric_names [0 ]). signature )
357+ j = outcomes .index (metric_name_to_signature [ c .metric_names [0 ]] )
349358 A [i , j ] = s
350359 b [i , 0 ] = s * c .bound
351360 return (A , b )
@@ -658,18 +667,18 @@ def get_pareto_frontier_and_configs(
658667 objective_weights = extract_objective_weight_matrix (
659668 objective = optimization_config .objective ,
660669 outcomes = adapter .outcomes ,
661- experiment = adapter ._experiment ,
670+ metric_name_to_signature = adapter .metric_name_to_signature ,
662671 )
663672 outcome_constraints = extract_outcome_constraints (
664673 outcome_constraints = optimization_config .outcome_constraints ,
665674 outcomes = adapter .outcomes ,
666- experiment = adapter ._experiment ,
675+ metric_name_to_signature = adapter .metric_name_to_signature ,
667676 )
668677 obj_t = extract_objective_thresholds (
669678 objective_thresholds = optimization_config .objective_thresholds ,
670679 objective = optimization_config .objective ,
671680 outcomes = adapter .outcomes ,
672- experiment = adapter ._experiment ,
681+ metric_name_to_signature = adapter .metric_name_to_signature ,
673682 )
674683 if obj_t is not None :
675684 obj_t = array_to_tensor (obj_t )
@@ -1128,7 +1137,7 @@ def observation_features_to_array(
11281137def feasible_hypervolume (
11291138 optimization_config : MultiObjectiveOptimizationConfig ,
11301139 values : dict [str , npt .NDArray ],
1131- experiment : Experiment ,
1140+ metric_name_to_signature : Mapping [ str , str ] ,
11321141) -> npt .NDArray :
11331142 """Compute the feasible hypervolume each iteration.
11341143
@@ -1137,26 +1146,26 @@ def feasible_hypervolume(
11371146 values: Dictionary from metric name to array of value at each
11381147 iteration (each array is `n`-dim). If optimization config contains
11391148 outcome constraints, values for them must be present in `values`.
1140- experiment: The experiment, used to map metric names to signatures.
1149+ metric_name_to_signature: Mapping from metric names to signatures.
11411150
11421151 Returns: Array of feasible hypervolumes.
11431152 """
11441153 # Get objective at each iteration
11451154 obj_threshold_dict = {
1146- experiment . get_metric ( ot .metric_names [0 ]). signature : ot .bound
1155+ metric_name_to_signature [ ot .metric_names [0 ]] : ot .bound
11471156 for ot in optimization_config .objective_thresholds
11481157 }
11491158 obj_metric_names = optimization_config .objective .metric_names
1150- obj_metrics = [experiment . get_metric ( name ) for name in obj_metric_names ]
1151- f_vals = np .hstack ([values [m . signature ].reshape (- 1 , 1 ) for m in obj_metrics ])
1152- obj_thresholds = np .array ([obj_threshold_dict [m . signature ] for m in obj_metrics ])
1159+ obj_metric_sigs = [metric_name_to_signature [ name ] for name in obj_metric_names ]
1160+ f_vals = np .hstack ([values [sig ].reshape (- 1 , 1 ) for sig in obj_metric_sigs ])
1161+ obj_thresholds = np .array ([obj_threshold_dict [sig ] for sig in obj_metric_sigs ])
11531162 # Set infeasible points to be the objective threshold
11541163 for oc in optimization_config .outcome_constraints :
11551164 if oc .relative :
11561165 raise ValueError (
11571166 "Benchmark aggregation does not support relative constraints"
11581167 )
1159- oc_sig = experiment . get_metric ( oc .metric_names [0 ]). signature
1168+ oc_sig = metric_name_to_signature [ oc .metric_names [0 ]]
11601169 g = values [oc_sig ]
11611170 feas = g <= oc .bound if oc .op == ComparisonOp .LEQ else g >= oc .bound
11621171 f_vals [~ feas ] = obj_thresholds
0 commit comments