Skip to content

Commit 14ea11a

Browse files
committed
move integration tests into acquisition
1 parent 4aab0b8 commit 14ea11a

File tree

2 files changed

+247
-251
lines changed

2 files changed

+247
-251
lines changed

tests/test_acquisition.py

Lines changed: 247 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,38 @@
55
import numpy as np
66
import pytest
77
from scipy.spatial.distance import pdist
8+
from scipy.optimize import NonlinearConstraint
89
from sklearn.gaussian_process import GaussianProcessRegressor
910

10-
from bayes_opt import acquisition, exception
11+
from bayes_opt import acquisition, exception, BayesianOptimization
1112
from bayes_opt.constraint import ConstraintModel
1213
from bayes_opt.target_space import TargetSpace
14+
from bayes_opt.acquisition import (
15+
UpperConfidenceBound,
16+
ProbabilityOfImprovement,
17+
ExpectedImprovement,
18+
ConstantLiar,
19+
GPHedge
20+
)
21+
22+
# Test fixtures
23+
@pytest.fixture
24+
def target_func_x_and_y():
25+
return lambda x, y: -(x - 1)**2 - (y - 2)**2
26+
27+
28+
@pytest.fixture
29+
def pbounds():
30+
return {"x": (-5, 5), "y": (-5, 5)}
31+
1332

33+
@pytest.fixture
34+
def constraint(constraint_func):
35+
return NonlinearConstraint(
36+
fun=constraint_func,
37+
lb=-1.0,
38+
ub=4.0
39+
)
1440

1541
@pytest.fixture
1642
def target_func():
@@ -32,6 +58,11 @@ def target_space(target_func):
3258
return TargetSpace(target_func=target_func, pbounds={"x": (1, 4), "y": (0, 3.0)})
3359

3460

61+
@pytest.fixture
62+
def constraint_func():
63+
return lambda x, y: x + y
64+
65+
3566
@pytest.fixture
3667
def constrained_target_space(target_func):
3768
constraint_model = ConstraintModel(fun=lambda params: params["x"] + params["y"], lb=0.0, ub=1.0)
@@ -357,3 +388,218 @@ def test_gphedge_integration(gp, target_space, random_state):
357388
def test_upper_confidence_bound_invalid_kappa_error(kappa: float):
358389
with pytest.raises(ValueError, match="kappa must be greater than or equal to 0."):
359390
acquisition.UpperConfidenceBound(kappa=kappa)
391+
392+
393+
def verify_optimizers_match(optimizer1, optimizer2):
394+
"""Helper function to verify two optimizers match."""
395+
assert len(optimizer1.space) == len(optimizer2.space)
396+
assert optimizer1.max["target"] == optimizer2.max["target"]
397+
assert optimizer1.max["params"] == optimizer2.max["params"]
398+
399+
400+
401+
np.testing.assert_array_equal(optimizer1.space.params, optimizer2.space.params)
402+
np.testing.assert_array_equal(optimizer1.space.target, optimizer2.space.target)
403+
404+
if optimizer1.is_constrained:
405+
np.testing.assert_array_equal(
406+
optimizer1.space._constraint_values,
407+
optimizer2.space._constraint_values
408+
)
409+
assert optimizer1.space._constraint.lb == optimizer2.space._constraint.lb
410+
assert optimizer1.space._constraint.ub == optimizer2.space._constraint.ub
411+
412+
assert np.random.get_state()[1][0] == np.random.get_state()[1][0]
413+
414+
assert optimizer1._gp.kernel.get_params() == optimizer2._gp.kernel.get_params()
415+
416+
suggestion1 = optimizer1.suggest()
417+
suggestion2 = optimizer2.suggest()
418+
assert suggestion1 == suggestion2, f"\nSuggestion 1: {suggestion1}\nSuggestion 2: {suggestion2}"
419+
420+
421+
422+
423+
def test_integration_upper_confidence_bound(target_func_x_and_y, pbounds, tmp_path):
424+
"""Test save/load integration with UpperConfidenceBound acquisition."""
425+
acquisition_function = UpperConfidenceBound(kappa=2.576)
426+
427+
# Create and run first optimizer
428+
optimizer = BayesianOptimization(
429+
f=target_func_x_and_y,
430+
pbounds=pbounds,
431+
acquisition_function=acquisition_function,
432+
random_state=1,
433+
verbose=0
434+
)
435+
optimizer.maximize(init_points=2, n_iter=3)
436+
437+
# Save state
438+
state_path = tmp_path / "ucb_state.json"
439+
optimizer.save_state(state_path)
440+
441+
# Create new optimizer and load state
442+
new_optimizer = BayesianOptimization(
443+
f=target_func_x_and_y,
444+
pbounds=pbounds,
445+
acquisition_function=UpperConfidenceBound(kappa=2.576),
446+
random_state=1,
447+
verbose=0
448+
)
449+
new_optimizer.load_state(state_path)
450+
451+
verify_optimizers_match(optimizer, new_optimizer)
452+
453+
def test_integration_probability_improvement(target_func_x_and_y, pbounds, tmp_path):
454+
"""Test save/load integration with ProbabilityOfImprovement acquisition."""
455+
acquisition_function = ProbabilityOfImprovement(xi=0.01)
456+
457+
optimizer = BayesianOptimization(
458+
f=target_func_x_and_y,
459+
pbounds=pbounds,
460+
acquisition_function=acquisition_function,
461+
random_state=1,
462+
verbose=0
463+
)
464+
optimizer.maximize(init_points=2, n_iter=3)
465+
466+
state_path = tmp_path / "pi_state.json"
467+
optimizer.save_state(state_path)
468+
469+
new_optimizer = BayesianOptimization(
470+
f=target_func_x_and_y,
471+
pbounds=pbounds,
472+
acquisition_function=ProbabilityOfImprovement(xi=0.01),
473+
random_state=1,
474+
verbose=0
475+
)
476+
new_optimizer.load_state(state_path)
477+
478+
verify_optimizers_match(optimizer, new_optimizer)
479+
480+
def test_integration_expected_improvement(target_func_x_and_y, pbounds, tmp_path):
481+
"""Test save/load integration with ExpectedImprovement acquisition."""
482+
acquisition_function = ExpectedImprovement(xi=0.01)
483+
484+
optimizer = BayesianOptimization(
485+
f=target_func_x_and_y,
486+
pbounds=pbounds,
487+
acquisition_function=acquisition_function,
488+
random_state=1,
489+
verbose=0
490+
)
491+
optimizer.maximize(init_points=2, n_iter=3)
492+
493+
state_path = tmp_path / "ei_state.json"
494+
optimizer.save_state(state_path)
495+
496+
new_optimizer = BayesianOptimization(
497+
f=target_func_x_and_y,
498+
pbounds=pbounds,
499+
acquisition_function=ExpectedImprovement(xi=0.01),
500+
random_state=1,
501+
verbose=0
502+
)
503+
new_optimizer.load_state(state_path)
504+
505+
verify_optimizers_match(optimizer, new_optimizer)
506+
507+
def test_integration_constant_liar(target_func_x_and_y, pbounds, tmp_path):
508+
"""Test save/load integration with ConstantLiar acquisition."""
509+
base_acq = UpperConfidenceBound(kappa=2.576)
510+
acquisition_function = ConstantLiar(base_acquisition=base_acq)
511+
512+
optimizer = BayesianOptimization(
513+
f=target_func_x_and_y,
514+
pbounds=pbounds,
515+
acquisition_function=acquisition_function,
516+
random_state=1,
517+
verbose=0
518+
)
519+
optimizer.maximize(init_points=2, n_iter=3)
520+
521+
state_path = tmp_path / "cl_state.json"
522+
optimizer.save_state(state_path)
523+
524+
new_optimizer = BayesianOptimization(
525+
f=target_func_x_and_y,
526+
pbounds=pbounds,
527+
acquisition_function=ConstantLiar(base_acquisition=UpperConfidenceBound(kappa=2.576)),
528+
random_state=1,
529+
verbose=0
530+
)
531+
new_optimizer.load_state(state_path)
532+
533+
verify_optimizers_match(optimizer, new_optimizer)
534+
535+
def test_integration_gp_hedge(target_func_x_and_y, pbounds, tmp_path):
536+
"""Test save/load integration with GPHedge acquisition."""
537+
base_acquisitions = [
538+
UpperConfidenceBound(kappa=2.576),
539+
ProbabilityOfImprovement(xi=0.01),
540+
ExpectedImprovement(xi=0.01)
541+
]
542+
acquisition_function = GPHedge(base_acquisitions=base_acquisitions)
543+
544+
optimizer = BayesianOptimization(
545+
f=target_func_x_and_y,
546+
pbounds=pbounds,
547+
acquisition_function=acquisition_function,
548+
random_state=1,
549+
verbose=0
550+
)
551+
optimizer.maximize(init_points=2, n_iter=3)
552+
553+
state_path = tmp_path / "gphedge_state.json"
554+
optimizer.save_state(state_path)
555+
556+
new_base_acquisitions = [
557+
UpperConfidenceBound(kappa=2.576),
558+
ProbabilityOfImprovement(xi=0.01),
559+
ExpectedImprovement(xi=0.01)
560+
]
561+
new_optimizer = BayesianOptimization(
562+
f=target_func_x_and_y,
563+
pbounds=pbounds,
564+
acquisition_function=GPHedge(base_acquisitions=new_base_acquisitions),
565+
random_state=1,
566+
verbose=0
567+
)
568+
new_optimizer.load_state(state_path)
569+
570+
# Print new optimizer state
571+
print("\nNew Optimizer State:")
572+
print(f"GP random state: {new_optimizer._gp.random_state}")
573+
print(f"GP kernel params:\n{new_optimizer._gp.kernel_.get_params()}")
574+
print(f"Global random state: {np.random.get_state()[1][0]}")
575+
576+
verify_optimizers_match(optimizer, new_optimizer)
577+
578+
def test_integration_constrained(target_func_x_and_y, pbounds, constraint, tmp_path):
579+
"""Test save/load integration with constraints."""
580+
acquisition_function = ExpectedImprovement(xi=0.01)
581+
582+
optimizer = BayesianOptimization(
583+
f=target_func_x_and_y,
584+
pbounds=pbounds,
585+
acquisition_function=acquisition_function,
586+
constraint=constraint,
587+
random_state=1,
588+
verbose=0
589+
)
590+
optimizer.maximize(init_points=2, n_iter=3)
591+
592+
state_path = tmp_path / "constrained_state.json"
593+
optimizer.save_state(state_path)
594+
595+
new_optimizer = BayesianOptimization(
596+
f=target_func_x_and_y,
597+
pbounds=pbounds,
598+
acquisition_function=ExpectedImprovement(xi=0.01),
599+
constraint=constraint,
600+
random_state=1,
601+
verbose=0
602+
)
603+
new_optimizer.load_state(state_path)
604+
605+
verify_optimizers_match(optimizer, new_optimizer)

0 commit comments

Comments
 (0)