3636import os
3737import warnings
3838
39- import cocoex
4039import numpy as np
4140from tqdm import tqdm
4241
4342from das .env .das_env import DASEnv
43+ from das .env .ioh_suite import IOHSuite
4444from das .optimizers .portfolio import get_portfolio
4545from das .utils import set_seed
4646from das .env .bbob_splits import ALL_DIMS , get_train_test_split
47- from das .training .common import compute_run_stats , load_global_optima
47+ from das .training .common import (
48+ compute_run_stats ,
49+ get_ioh_optimum ,
50+ ERT_TARGETS ,
51+ _ert_key ,
52+ )
4853
4954warnings .filterwarnings ("ignore" )
5055
@@ -95,7 +100,6 @@ def collect_env_results(
95100 suite ,
96101 optimizers : list ,
97102 cfg : dict ,
98- global_optima : dict [str , float ],
99103) -> list [dict ]:
100104 """Run policy_fn on every problem in test_ids via DASEnv."""
101105 env = DASEnv (
@@ -112,7 +116,7 @@ def collect_env_results(
112116 for problem_id in tqdm (test_ids , desc = f" { agent_tag } " , smoothing = 0.0 ):
113117 step_info , fitness_history = run_episode (env , policy_fn )
114118 max_fe = step_info .get ("n_fe" , 0 )
115- global_minimum = global_optima . get (problem_id , 0.0 )
119+ global_minimum = get_ioh_optimum (problem_id )
116120 stats = compute_run_stats (fitness_history , max_fe , global_minimum )
117121 results .append ({problem_id : {** stats , "agent" : agent_tag }})
118122 env .close ()
@@ -164,13 +168,12 @@ def collect_single_results(
164168 suite ,
165169 fe_multiplier : int ,
166170 n_individuals : int ,
167- global_optima : dict [str , float ],
168171) -> list [dict ]:
169172 """Run the optimizer independently on every problem in test_ids."""
170173 results = []
171174 for problem_id in tqdm (test_ids , desc = f" { agent_tag } " , smoothing = 0.0 ):
172175 problem = suite .get_problem (problem_id )
173- global_minimum = global_optima . get (problem_id , 0.0 )
176+ global_minimum = get_ioh_optimum (problem_id )
174177 stats = run_single_algorithm (
175178 optimizer_class , problem , fe_multiplier , n_individuals , global_minimum
176179 )
@@ -212,6 +215,8 @@ def compute_oracle(all_results: dict[str, list[dict]]) -> tuple[list[dict], list
212215 ],
213216 "aocc" : best_m ["aocc" ],
214217 "final_fitness" : best_m ["final_fitness" ],
218+ "hitting_times" : best_m .get ("hitting_times" , {}),
219+ "max_fe" : best_m .get ("max_fe" , 0 ),
215220 "agent" : "oracle-best" ,
216221 "best_agent" : best_m ["agent" ],
217222 }
@@ -225,6 +230,8 @@ def compute_oracle(all_results: dict[str, list[dict]]) -> tuple[list[dict], list
225230 ],
226231 "aocc" : worst_m ["aocc" ],
227232 "final_fitness" : worst_m ["final_fitness" ],
233+ "hitting_times" : worst_m .get ("hitting_times" , {}),
234+ "max_fe" : worst_m .get ("max_fe" , 0 ),
228235 "agent" : "oracle-worst" ,
229236 "worst_agent" : worst_m ["agent" ],
230237 }
@@ -241,12 +248,29 @@ def compute_oracle(all_results: dict[str, list[dict]]) -> tuple[list[dict], list
241248# ------------------------------------------------------------------ #
242249
243250
251+ def _ert_for_target (records : list [dict ], target_key : str ) -> float | None :
252+ """ERT = total_FEs / n_successful_runs (unsuccessful runs contribute max_fe)."""
253+ total_fe = 0
254+ n_succ = 0
255+ for r in records :
256+ m = next (iter (r .values ()))
257+ ht = m .get ("hitting_times" , {}).get (target_key )
258+ mfe = m .get ("max_fe" , 0 )
259+ if ht is not None :
260+ total_fe += ht
261+ n_succ += 1
262+ else :
263+ total_fe += mfe
264+ return float (total_fe / n_succ ) if n_succ > 0 else None
265+
266+
244267def summarise (tag : str , records : list [dict ]) -> dict :
245268 fitnesses = [next (iter (r .values ()))["final_fitness" ] for r in records ]
246269 aocc_vals = [next (iter (r .values ()))["aocc" ] for r in records ]
247270 auoc_vals = [
248271 next (iter (r .values ()))["area_under_optimization_curve" ] for r in records
249272 ]
273+ ert = {_ert_key (t ): _ert_for_target (records , _ert_key (t )) for t in ERT_TARGETS }
250274 return {
251275 "agent" : tag ,
252276 "n_problems" : len (fitnesses ),
@@ -256,6 +280,7 @@ def summarise(tag: str, records: list[dict]) -> dict:
256280 "worst_final_fitness" : float (np .max (fitnesses )),
257281 "mean_aocc" : float (np .mean (aocc_vals )),
258282 "mean_auoc" : float (np .mean (auoc_vals )),
283+ "ert" : ert ,
259284 }
260285
261286
@@ -266,16 +291,23 @@ def save_results(records: list[dict], path: str) -> None:
266291
267292
268293def print_summary (summaries : list [dict ]) -> None :
294+ _ERT_PRINT_TARGET = "1e-04"
269295 width = max (len (s ["agent" ]) for s in summaries ) + 2
270- header = f" { 'Agent' :<{width }} { 'Mean fitness' :>14} { 'Median fitness' :>14} { 'Mean AUOC' :>14} "
296+ header = (
297+ f" { 'Agent' :<{width }} { 'Mean fitness' :>14} { 'Median fitness' :>14} "
298+ f" { 'Mean AUOC' :>14} { 'ERT(1e-04)' :>12} "
299+ )
271300 print (header )
272301 print (" " + "-" * (len (header ) - 2 ))
273302 for s in summaries :
303+ ert_val = s .get ("ert" , {}).get (_ERT_PRINT_TARGET )
304+ ert_str = f"{ ert_val :>12.1f} " if ert_val is not None else f"{ 'inf' :>12} "
274305 print (
275306 f" { s ['agent' ]:<{width }} "
276307 f"{ s ['mean_final_fitness' ]:>14.4e} "
277308 f"{ s ['median_final_fitness' ]:>14.4e} "
278- f"{ s ['mean_auoc' ]:>14.4e} "
309+ f"{ s ['mean_auoc' ]:>14.4e} "
310+ f"{ ert_str } "
279311 )
280312
281313
@@ -317,7 +349,7 @@ def parse_args():
317349 p .add_argument ("-s" , "--n-checkpoints" , type = int , default = 10 )
318350 p .add_argument ("-x" , "--cdb" , type = float , default = 1.0 )
319351 p .add_argument ("-O" , "--reward-option" , type = int , default = 1 , choices = [1 , 2 , 3 , 4 ])
320- p .add_argument ("-n" , "--n-individuals" , type = int , default = 100 )
352+ p .add_argument ("-n" , "--n-individuals" , type = int , default = None )
321353 p .add_argument ("--seed" , type = int , default = 42 )
322354 return p .parse_args ()
323355
@@ -334,11 +366,8 @@ def main():
334366
335367 optimizers = get_portfolio (args .portfolio )
336368 opt_names = args .portfolio
337- cocoex .utilities .MiniPrint ()
338- suite = cocoex .Suite ("bbob" , "" , "" )
369+ suite = IOHSuite ()
339370 _ , test_ids = get_train_test_split (args .mode , args .dims )
340- global_optima = load_global_optima ()
341-
342371 cfg = {
343372 "fe_multiplier" : args .fe_multiplier ,
344373 "n_checkpoints" : args .n_checkpoints ,
@@ -384,7 +413,7 @@ def main():
384413
385414 if tag == "random" :
386415 records = collect_env_results (
387- tag , random_policy , test_ids , suite , optimizers , cfg , global_optima
416+ tag , random_policy , test_ids , suite , optimizers , cfg
388417 )
389418
390419 elif tag .startswith ("fixed:" ):
@@ -402,7 +431,6 @@ def main():
402431 suite ,
403432 optimizers ,
404433 cfg ,
405- global_optima ,
406434 )
407435
408436 elif tag .startswith ("single:" ):
@@ -415,7 +443,6 @@ def main():
415443 suite ,
416444 args .fe_multiplier ,
417445 args .n_individuals ,
418- global_optima ,
419446 )
420447
421448 else :
0 commit comments