11"""Adapter for gfo package."""
2+
23# copyright: hyperactive developers, MIT License (see LICENSE file)
34
45from hyperactive .base import BaseOptimizer
@@ -40,9 +41,7 @@ def _get_gfo_class(self):
4041 class
4142 The GFO class to use. One of the concrete GFO classes
4243 """
43- raise NotImplementedError (
44- "This method should be implemented in a subclass."
45- )
44+ raise NotImplementedError ("This method should be implemented in a subclass." )
4645
4746 def get_search_config (self ):
4847 """Get the search configuration.
@@ -55,8 +54,63 @@ def get_search_config(self):
5554 search_config = super ().get_search_config ()
5655 search_config ["initialize" ] = self ._initialize
5756 del search_config ["verbose" ]
57+
58+ search_config = self ._handle_gfo_defaults (search_config )
59+
60+ search_config ["search_space" ] = self ._to_dict_np (search_config ["search_space" ])
61+
62+ return search_config
63+
64+ def _handle_gfo_defaults (self , search_config ):
65+ """Handle default values for GFO search configuration.
66+
67+ Temporary measure until GFO handles defaults gracefully.
68+
69+ Parameters
70+ ----------
71+ search_config : dict with str keys
72+ The search configuration dictionary to handle defaults for.
73+
74+ Returns
75+ -------
76+ search_config : dict with str keys
77+ The search configuration dictionary with defaults handled.
78+ """
79+ if "sampling" in search_config and search_config ["sampling" ] is None :
80+ search_config ["sampling" ] = {"random" : 1000000 }
81+
82+ if "tree_para" in search_config and search_config ["tree_para" ] is None :
83+ search_config ["tree_para" ] = {"n_estimators" : 100 }
84+
5885 return search_config
5986
87+ def _to_dict_np (self , search_space ):
88+ """Coerce the search space to a format suitable for gfo optimizers.
89+
90+ gfo expects dicts of numpy arrays, not lists.
91+ This method coerces lists or tuples in the search space to numpy arrays.
92+
93+ Parameters
94+ ----------
95+ search_space : dict with str keys and iterable values
96+ The search space to coerce.
97+
98+ Returns
99+ -------
100+ dict with str keys and 1D numpy arrays as values
101+ The coerced search space.
102+ """
103+ import numpy as np
104+
105+ def coerce_to_numpy (arr ):
106+ """Coerce a list or tuple to a numpy array."""
107+ if not isinstance (arr , np .ndarray ):
108+ return np .array (arr )
109+ return arr
110+
111+ coerced_search_space = {k : coerce_to_numpy (v ) for k , v in search_space .items ()}
112+ return coerced_search_space
113+
60114 def _run (self , experiment , ** search_config ):
61115 """Run the optimization search process.
62116 Parameters
@@ -75,15 +129,15 @@ def _run(self, experiment, **search_config):
75129 max_time = search_config .pop ("max_time" , None )
76130
77131 gfo_cls = self ._get_gfo_class ()
78- hcopt = gfo_cls (** search_config )
132+ gfopt = gfo_cls (** search_config )
79133
80134 with StdoutMute (active = not self .verbose ):
81- hcopt .search (
135+ gfopt .search (
82136 objective_function = experiment .score ,
83137 n_iter = n_iter ,
84138 max_time = max_time ,
85139 )
86- best_params = hcopt .best_para
140+ best_params = gfopt .best_para
87141 return best_params
88142
89143 @classmethod
@@ -143,5 +197,12 @@ def get_test_params(cls, parameter_set="default"):
143197 },
144198 "n_iter" : 100 ,
145199 }
146-
147- return [params_sklearn , params_ackley ]
200+ params_ackley_list = {
201+ "experiment" : ackley_exp ,
202+ "search_space" : {
203+ "x0" : list (np .linspace (- 5 , 5 , 10 )),
204+ "x1" : list (np .linspace (- 5 , 5 , 10 )),
205+ },
206+ "n_iter" : 100 ,
207+ }
208+ return [params_sklearn , params_ackley , params_ackley_list ]
0 commit comments