1313 Bounds , NonlinearConstraint , rosen , minimize as scipy_minimize ,
1414 shgo as scipy_shgo ,
1515)
16+ from scipy .stats import gaussian_kde
1617
1718from sambo import minimize , Optimizer , SamboSearchCV
1819from sambo ._space import Space
1920from sambo ._sceua import sceua
2021from sambo ._shgo import shgo
2122from sambo ._smbo import smbo
2223from sambo .plot import plot_convergence , plot_evaluations , plot_objective , plot_regret
23- from sambo ._util import OptimizeResult
24-
24+ from sambo ._util import OptimizeResult , recompute_kde , weighted_uniform_sampling
2525
2626minimize = partial (minimize , rng = 0 )
2727sceua = partial (sceua , rng = 0 )
@@ -214,7 +214,7 @@ def test_sceua(self):
214214
215215 def test_smbo (self ):
216216 res = minimize (** ROSEN_TEST_PARAMS , method = 'smbo' , max_iter = 20 , estimator = 'gp' )
217- check_result (res , 0 , atol = 55 )
217+ check_result (res , 0 , atol = 5 )
218218
219219 def test_args (self ):
220220 def f (x , a ):
@@ -240,7 +240,7 @@ def f(x):
240240
241241 counter = 0
242242 _ = _minimize (f , method = 'smbo' )
243- self .assertEqual (counter , MAX_ITER )
243+ self .assertLessEqual (counter , MAX_ITER )
244244
245245 def test_constraints (self ):
246246 def f (x ):
@@ -313,16 +313,11 @@ def test_our_params_match_scipy_optimize_params(self):
313313
314314class TestSklearnEstimators (unittest .TestCase ):
315315 def test_estimator_factory (self ):
316- DEFAULT_KWARGS = {'max_iter' : 50 , 'n_iter_no_change' : 10 , 'rng' : 0 }
317- ESTIMATOR_KWARGS = {
318- 'gp' : {},
319- 'et' : {'n_iter_no_change' : 40 },
320- 'gb' : {'n_iter_no_change' : 20 , 'rng' : 2 },
321- }
316+ DEFAULT_KWARGS = {'max_iter' : 20 , 'n_iter_no_change' : 5 , 'rng' : 0 }
322317 for estimator in BUILTIN_ESTIMATORS :
323318 with self .subTest (estimator = estimator ):
324319 res = smbo (lambda x : sum ((x - 2 )** 2 ), bounds = [(- 100 , 100 )], estimator = estimator ,
325- ** dict (DEFAULT_KWARGS , ** ESTIMATOR_KWARGS [ estimator ] ))
320+ ** dict (DEFAULT_KWARGS ))
326321 self .assertLess (res .fun , 1 , msg = res )
327322
328323 def test_SamboSearchCV_large_param_grid (self ):
@@ -353,11 +348,17 @@ def test_SamboSearchCV_large_param_grid(self):
353348
354349class TestDocs (unittest .TestCase ):
355350 def test_make_doc_plots (self ):
351+ KWARGS = {
352+ 'shgo' : dict (n_init = 30 ),
353+ 'smbo' : dict (n_init = 30 ),
354+ 'sceua' : dict (n_complexes = 3 ),
355+ }
356356 results = [
357357 minimize (
358- rosen , bounds = [(- 2. , 2. ), (- 2. , 2. )],
359- constraints = lambda x : sum (x ** 2 ) <= 2 * len (x ),
360- max_iter = 120 , method = method , rng = 2 ,
358+ rosen , bounds = [(- 2. , 2. )]* 2 ,
359+ constraints = lambda x : sum (x ** 2 ) <= 2 ** len (x ),
360+ max_iter = 100 , method = method , rng = 2 ,
361+ ** KWARGS .get (method , {}),
361362 )
362363 for method in BUILTIN_METHODS
363364 ]
@@ -392,7 +393,7 @@ def test_make_doc_plots(self):
392393 def test_website_example1 (self ):
393394 res = minimize (
394395 rosen , bounds = [(- 2. , 2. ), ] * 2 ,
395- constraints = lambda x : sum (x ** 2 ) <= len (x ),
396+ constraints = lambda x : sum (x ** 2 ) <= 2 ** len (x ),
396397 n_init = 7 , method = 'shgo' , rng = 0 ,
397398 )
398399 print (type (res ), res , sep = '\n \n ' )
@@ -478,5 +479,35 @@ def test_annotations(self):
478479 annot [arg ], annot_ref [arg ], msg = f'{ fun .__qualname__ } / { arg } ' )
479480
480481
482+ class TestUtil (unittest .TestCase ):
483+ def test_weighted_uniform_sampling (self ):
484+ rng = np .random .default_rng (2 )
485+ X = rng .uniform (- 10 , 10 , (100 , 2 ))
486+ y = rng .uniform (1 , 10 , 100 )
487+ bounds = [(- 10 , 10 ), (- 10 , 10 )]
488+ n_samples = 10000
489+ kde = recompute_kde (X , y )
490+ sampled_points = weighted_uniform_sampling (kde , bounds , n_samples , None , 0 )
491+
492+ # Verify results
493+ hist , xedges , yedges = np .histogram2d (* sampled_points .T , range = bounds )
494+ # Compare histogram density with weight distribution
495+ kde = gaussian_kde (X .T , weights = (np .max (y ) - y ) / np .sum (np .max (y ) - y ))
496+ test_grid = np .array (np .meshgrid (xedges [:- 1 ], yedges [:- 1 ])).T .reshape (- 1 , 2 )
497+ pdf_values = kde (test_grid .T ).reshape (hist .shape )
498+ # Normalize for direct comparison
499+ hist_normalized = hist / np .sum (hist )
500+ pdf_normalized = pdf_values / np .sum (pdf_values )
501+ # Plot results
502+ fig , axes = plt .subplots (1 , 2 , figsize = (8 , 4 ))
503+ extent = np .array (bounds ).flatten ()
504+ axes [0 ].imshow (hist_normalized , extent = extent , origin = 'lower' , cmap = 'Blues' )
505+ axes [1 ].imshow (pdf_normalized , extent = extent , origin = 'lower' , cmap = 'Reds' )
506+ plt .show ()
507+
508+ diff = np .abs (hist_normalized - pdf_normalized ).mean ()
509+ self .assertLess (diff , .05 )
510+
511+
481512if __name__ == '__main__' :
482513 unittest .main ()
0 commit comments