@@ -133,13 +133,14 @@ class Spot:
133133 Examples:
134134 >>> import numpy as np
135135 from math import inf
136+ from scipy.optimize import differential_evolution
136137 from spotpython.spot import spot
137138 from spotpython.utils.init import (
138139 fun_control_init,
139140 design_control_init,
140141 surrogate_control_init,
141142 optimizer_control_init)
142- def objective_function(X, fun_control=None ):
143+ def objective_function(X, **kwargs ):
143144 if not isinstance(X, np.ndarray):
144145 X = np.array(X)
145146 if X.shape[1] != 2:
@@ -303,6 +304,22 @@ def _set_fun(self, fun):
303304 Exception: No objective function specified.
304305 Exception: Objective function is not callable
305306
307+ Examples:
308+ >>> import numpy as np
309+ from spotpython.spot import spot
310+ from spotpython.utils.init import fun_control_init
311+
312+ def objective_function(X):
313+ return np.sum(X, axis=1)
314+
315+ fun_control = fun_control_init(
316+ lower=np.array([0, 0]),
317+ upper=np.array([5, 5]),
318+ seed=12345
319+ )
320+
321+ S = spot.Spot(fun=objective_function, fun_control=fun_control)
322+ print(S.fun(np.array([[1, 2], [3, 4]])))
306323 """
307324 self .fun = fun
308325 if self .fun is None :
@@ -318,6 +335,21 @@ def _set_bounds_and_dim(self) -> None:
318335 Returns:
319336 (NoneType): None
320337
338+ Examples:
339+ >>> import numpy as np
340+ from spotpython.spot import spot
341+ from spotpython.utils.init import fun_control_init
342+
343+ fun_control = fun_control_init(
344+ lower=np.array([-1, -1]),
345+ upper=np.array([1, 1])
346+ )
347+
348+ S = spot.Spot(fun=lambda x: x, fun_control=fun_control)
349+ print("Lower bounds:", S.lower)
350+ print("Upper bounds:", S.upper)
351+ print("Number of dimensions (k):", S.k)
352+
321353 """
322354 # lower attribute updates:
323355 # if lower is in the fun_control dictionary, use the value of the key "lower" as the lower bound
@@ -336,6 +368,20 @@ def _set_var_type(self) -> None:
336368 Set the variable types based on the fun_control dictionary.
337369 If the variable types are not specified,
338370 all variable types are forced to 'num'.
371+
372+ Examples:
373+ >>> import numpy as np
374+ from spotpython.spot import spot
375+ from spotpython.utils.init import fun_control_init
376+
377+ fun_control = fun_control_init(
378+ lower=np.array([0, 0]),
379+ upper=np.array([10, 10]),
380+ var_type=["num", "cat"]
381+ )
382+
383+ S = spot.Spot(fun=lambda x: x, fun_control=fun_control)
384+ print("Variable types:", S.var_type)
339385 """
340386 self .var_type = self .fun_control ["var_type" ]
341387 # Force numeric type as default in every dim:
@@ -345,11 +391,33 @@ def _set_var_type(self) -> None:
345391 self .var_type = self .var_type * self .k
346392 logger .warning ("All variable types forced to 'num'." )
347393
394+ # --- check for allowed variable types ---
395+ allowed_types = {"num" , "int" , "float" , "factor" }
396+ for vt in self .var_type :
397+ if vt not in allowed_types :
398+ raise ValueError (f"Invalid var_type '{ vt } '. Allowed types are: { allowed_types } ." )
399+ # "num" is the superset of "int" and "float"
400+ # (no further action needed, just a check)
401+
348402 def _set_var_name (self ) -> None :
349403 """
350404 Set the variable names based on the fun_control dictionary.
351405 If the variable names are not specified,
352406 all variable names are set to x0, x1, x2, ...
407+
408+ Examples:
409+ >>> import numpy as np
410+ from spotpython.spot import spot
411+ from spotpython.utils.init import fun_control_init
412+
413+ fun_control = fun_control_init(
414+ lower=np.array([0, 0]),
415+ upper=np.array([10, 10]),
416+ var_name=["length", "width"]
417+ )
418+
419+ S = spot.Spot(fun=lambda x: x, fun_control=fun_control)
420+ print("Variable names:", S.var_name)
353421 """
354422 self .var_name = self .fun_control ["var_name" ]
355423 # use x0, x1, ... as default variable names:
@@ -523,6 +591,7 @@ def _design_setup(self, design) -> None:
523591 def _optimizer_setup (self , optimizer ) -> None :
524592 """
525593 Optimizer setup. If no optimizer is specified, use Differential Evolution.
594+ The current implementation of _optimizer_setup always overwrites self.optimizer with the default if optimizer is None, even if self.optimizer was already set.
526595 """
527596 self .optimizer = optimizer
528597 if self .optimizer is None :
@@ -536,7 +605,7 @@ def _surrogate_control_setup(self) -> None:
536605 # to the value of the key "method" from the fun_control dictionary.
537606 # If the value is set (i.e., not None), it is not updated.
538607 if self .surrogate_control ["method" ] is None :
539- self .surrogate_control .update ({"method" : self .fun_control . method })
608+ self .surrogate_control .update ({"method" : self .fun_control [ " method" ] })
540609 if self .surrogate_control ["model_fun_evals" ] is None :
541610 self .surrogate_control .update ({"model_fun_evals" : self .optimizer_control ["max_iter" ]})
542611 # self.optimizer is not None here. If 1) the key "model_optimizer"
0 commit comments