@@ -58,9 +58,12 @@ class AbstractFacade:
5858 ----------
5959 scenario : Scenario
6060 The scenario object, holding all environmental information.
61- target_function : Callable | str | AbstractRunner
61+ target_function : Callable | str | AbstractRunner | None, defaults to None
6262 This function is called internally to judge a trial's performance. If a string is passed,
6363 it is assumed to be a script. In this case, ``TargetFunctionScriptRunner`` is used to run the script.
64+ In the rare case that only ``ask`` and ``tell`` and not ``optimize`` is used to optimize
65+ the hyperparameters, the target_function argument can be None, because SMAC no longer is
66+ charge of the evaluation of the configuration and thus does not need to know about it.
6467 model : AbstractModel | None, defaults to None
6568 The surrogate model.
6669 acquisition_function : AbstractAcquisitionFunction | None, defaults to None
@@ -105,7 +108,7 @@ class AbstractFacade:
105108 def __init__ (
106109 self ,
107110 scenario : Scenario ,
108- target_function : Callable | str | AbstractRunner ,
111+ target_function : Callable | str | AbstractRunner | None = None ,
109112 * ,
110113 model : AbstractModel | None = None ,
111114 acquisition_function : AbstractAcquisitionFunction | None = None ,
@@ -176,8 +179,10 @@ def __init__(
176179 self ._overwrite = overwrite
177180
178181 # Prepare the algorithm executer
179- runner : AbstractRunner
180- if isinstance (target_function , AbstractRunner ):
182+ runner : AbstractRunner | None
183+ if isinstance (target_function , AbstractRunner ) or target_function is None :
184+ # in case the target_function is None (e.g. we purely use ask & tell)
185+ # we let smbo.optimize raise an error
181186 runner = target_function
182187 elif isinstance (target_function , str ):
183188 runner = TargetFunctionScriptRunner (
@@ -193,7 +198,7 @@ def __init__(
193198 )
194199
195200 # In case of multiple jobs, we need to wrap the runner again using DaskParallelRunner
196- if (n_workers := scenario .n_workers ) > 1 or dask_client is not None :
201+ if (( n_workers := scenario .n_workers ) > 1 or dask_client is not None ) and runner is not None :
197202 if dask_client is not None and n_workers > 1 :
198203 logger .warning (
199204 "Provided `dask_client`. Ignore `scenario.n_workers`, directly set `n_workers` in `dask_client`."
@@ -265,7 +270,7 @@ def meta(self) -> dict[str, Any]:
265270
266271 meta = {
267272 "facade" : {"name" : self .__class__ .__name__ },
268- "runner" : self ._runner .meta ,
273+ "runner" : self ._runner .meta if self . _runner is not None else None ,
269274 "model" : self ._model .meta ,
270275 "acquisition_maximizer" : self ._acquisition_maximizer .meta ,
271276 "acquisition_function" : self ._acquisition_function .meta ,
0 commit comments