Skip to content

Commit

Permalink
Fix 478, fix data out-of-sync issue in target space (#479)
Browse files Browse the repository at this point in the history
* Fix 478, fix data out-of-sync issue in target space

* Add test logs file for multiple constraints

* Fix an unrelated bug in the visualization script.
  • Loading branch information
till-m committed Jun 25, 2024
1 parent ebd5401 commit 4aa6a97
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 6 deletions.
4 changes: 4 additions & 0 deletions bayes_opt/logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from __future__ import print_function
import os
import json
import numpy as np
from .observer import _Tracker
from .event import Events
from colorama import Fore, just_fix_windows_console
Expand Down Expand Up @@ -291,6 +292,9 @@ def update(self, event, instance):

if "allowed" in data: # fix: github.com/fmfn/BayesianOptimization/issues/361
data["allowed"] = bool(data["allowed"])

if "constraint" in data and isinstance(data["constraint"], np.ndarray):
data["constraint"] = data["constraint"].tolist()

with open(self._path, "a") as f:
f.write(json.dumps(data) + "\n")
Expand Down
21 changes: 15 additions & 6 deletions bayes_opt/target_space.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,21 +312,30 @@ def register(self, params, target, constraint_value=None):
if not np.all((self._bounds[:, 0] <= x) & (x <= self._bounds[:, 1])):
warn(f'\nData point {x} is outside the bounds of the parameter space. ', stacklevel=2)

self._params = np.concatenate([self._params, x.reshape(1, -1)])
self._target = np.concatenate([self._target, [target]])
# Make copies of the data, so as not to modify the originals incase something fails
# during the registration process. This prevents out-of-sync data.
params_copy = np.concatenate([self._params, x.reshape(1, -1)])
target_copy = np.concatenate([self._target, [target]])
cache_copy = self._cache.copy() # shallow copy suffices

if self._constraint is None:
# Insert data into unique dictionary
self._cache[_hashable(x.ravel())] = target
cache_copy[_hashable(x.ravel())] = target
else:
if constraint_value is None:
msg = ("When registering a point to a constrained TargetSpace" +
" a constraint value needs to be present.")
raise ValueError(msg)
# Insert data into unique dictionary
self._cache[_hashable(x.ravel())] = (target, constraint_value)
self._constraint_values = np.concatenate([self._constraint_values,
[constraint_value]])
cache_copy[_hashable(x.ravel())] = (target, constraint_value)
constraint_values_copy = np.concatenate([self._constraint_values,
[constraint_value]])
self._constraint_values = constraint_values_copy

# Operations passed, update the variables
self._params = params_copy
self._target = target_copy
self._cache = cache_copy

def probe(self, params):
"""Evaluate the target function on a point and register the result.
Expand Down
12 changes: 12 additions & 0 deletions tests/test_logs_multiple_constraints.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{"target": -34660.799399896976, "constraint": [0.2708972584125664, 0.42357209835559106], "params": {"x": -50.183952461055, "y": 180.28572256396646}, "allowed": true, "datetime": {"datetime": "2024-06-20 15:45:44", "elapsed": 0.0, "delta": 0.0}}
{"target": -10089.822899242456, "constraint": [-0.9510813312336377, 0.9973445494788389], "params": {"x": 92.79757672456203, "y": 39.46339367881464}, "allowed": false, "datetime": {"datetime": "2024-06-20 15:45:44", "elapsed": 0.000321, "delta": 0.000321}}
{"target": -10506.089080732436, "constraint": [0.6131701761022414, -0.9564999545661308], "params": {"x": 95.21519271989214, "y": 38.96256255900324}, "allowed": false, "datetime": {"datetime": "2024-06-20 15:45:44", "elapsed": 0.056496, "delta": 0.056175}}
{"target": -997.8139138494062, "constraint": [-0.9916913121401841, -0.6495843128640307], "params": {"x": 18.482175449759072, "y": -24.636362934194256}, "allowed": true, "datetime": {"datetime": "2024-06-20 15:45:44", "elapsed": 0.556892, "delta": 0.500396}}
{"target": -19477.39999548628, "constraint": [0.4566191751114183, 0.10531295488159137], "params": {"x": -30.134980186677655, "y": -135.2728254812192}, "allowed": true, "datetime": {"datetime": "2024-06-20 15:45:45", "elapsed": 1.025239, "delta": 0.468347}}
{"target": -2557.6177973621116, "constraint": [0.9347247196809806, 0.9180512307035334], "params": {"x": -49.8799963378478, "y": 9.402604518743091}, "allowed": false, "datetime": {"datetime": "2024-06-20 15:45:45", "elapsed": 1.359698, "delta": 0.334459}}
{"target": -39604.24318900592, "constraint": [0.8549175086147126, 0.9001717563474866], "params": {"x": -197.96772313017533, "y": -19.347574490837093}, "allowed": false, "datetime": {"datetime": "2024-06-20 15:45:45", "elapsed": 1.595204, "delta": 0.235506}}
{"target": -80400.0, "constraint": [-0.9999999999999999, 0.5252963386425359], "params": {"x": 200.0, "y": -200.0}, "allowed": true, "datetime": {"datetime": "2024-06-20 15:45:45", "elapsed": 1.788137, "delta": 0.192933}}
{"target": -79600.0, "constraint": [0.5252963386425359, -0.9999999999999999], "params": {"x": 200.0, "y": 200.0}, "allowed": true, "datetime": {"datetime": "2024-06-20 15:45:46", "elapsed": 2.146403, "delta": 0.358266}}
{"target": -80400.0, "constraint": [0.5252963386425359, -0.9999999999999999], "params": {"x": -200.0, "y": -200.0}, "allowed": true, "datetime": {"datetime": "2024-06-20 15:45:46", "elapsed": 2.518581, "delta": 0.372178}}
{"target": -79600.0, "constraint": [-0.9999999999999999, 0.5252963386425359], "params": {"x": -200.0, "y": 200.0}, "allowed": true, "datetime": {"datetime": "2024-06-20 15:45:47", "elapsed": 3.028643, "delta": 0.510062}}
{"target": -4290.396951749328, "constraint": [-0.32857141283617775, -0.3643611387948609], "params": {"x": -8.207850284687554, "y": 65.99252376584158}, "allowed": true, "datetime": {"datetime": "2024-06-20 15:45:47", "elapsed": 3.494066, "delta": 0.465423}}
34 changes: 34 additions & 0 deletions tests/test_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,40 @@ def c(x, y):
assert len(optimizer.space) == 7


def test_logs_constraint():

def f(x, y):
return -x ** 2 - (y - 1) ** 2 + 1

def c(x, y):
return np.array([
- np.cos(x) * np.cos(y) + np.sin(x) * np.sin(y),
- np.cos(x) * np.cos(-y) + np.sin(x) * np.sin(-y)
])

constraint_lower = np.array([-np.inf, -np.inf])
constraint_upper = np.array([0.6, 0.6])

constraint = NonlinearConstraint(c, constraint_lower, constraint_upper)

optimizer = BayesianOptimization(
f=f,
pbounds={"x": (-200, 200), "y": (-200, 200)},
constraint=constraint
)

with pytest.raises(KeyError):
load_logs(optimizer, [str(test_dir / "test_logs.log")])

with pytest.raises(ValueError):
load_logs(optimizer, [str(test_dir / "test_logs_constrained.log")])

load_logs(optimizer, [str(test_dir / "test_logs_multiple_constraints.log")])

print(optimizer.space)
assert len(optimizer.space) == 12


if __name__ == '__main__':
r"""
CommandLine:
Expand Down

0 comments on commit 4aa6a97

Please sign in to comment.