Skip to content

Commit 4aa6a97

Browse files
authored
Fix 478, fix data out-of-sync issue in target space (#479)
* 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.
1 parent ebd5401 commit 4aa6a97

File tree

4 files changed

+65
-6
lines changed

4 files changed

+65
-6
lines changed

bayes_opt/logger.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from __future__ import print_function
33
import os
44
import json
5+
import numpy as np
56
from .observer import _Tracker
67
from .event import Events
78
from colorama import Fore, just_fix_windows_console
@@ -291,6 +292,9 @@ def update(self, event, instance):
291292

292293
if "allowed" in data: # fix: github.com/fmfn/BayesianOptimization/issues/361
293294
data["allowed"] = bool(data["allowed"])
295+
296+
if "constraint" in data and isinstance(data["constraint"], np.ndarray):
297+
data["constraint"] = data["constraint"].tolist()
294298

295299
with open(self._path, "a") as f:
296300
f.write(json.dumps(data) + "\n")

bayes_opt/target_space.py

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -312,21 +312,30 @@ def register(self, params, target, constraint_value=None):
312312
if not np.all((self._bounds[:, 0] <= x) & (x <= self._bounds[:, 1])):
313313
warn(f'\nData point {x} is outside the bounds of the parameter space. ', stacklevel=2)
314314

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

318321
if self._constraint is None:
319322
# Insert data into unique dictionary
320-
self._cache[_hashable(x.ravel())] = target
323+
cache_copy[_hashable(x.ravel())] = target
321324
else:
322325
if constraint_value is None:
323326
msg = ("When registering a point to a constrained TargetSpace" +
324327
" a constraint value needs to be present.")
325328
raise ValueError(msg)
326329
# Insert data into unique dictionary
327-
self._cache[_hashable(x.ravel())] = (target, constraint_value)
328-
self._constraint_values = np.concatenate([self._constraint_values,
329-
[constraint_value]])
330+
cache_copy[_hashable(x.ravel())] = (target, constraint_value)
331+
constraint_values_copy = np.concatenate([self._constraint_values,
332+
[constraint_value]])
333+
self._constraint_values = constraint_values_copy
334+
335+
# Operations passed, update the variables
336+
self._params = params_copy
337+
self._target = target_copy
338+
self._cache = cache_copy
330339

331340
def probe(self, params):
332341
"""Evaluate the target function on a point and register the result.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{"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}}
2+
{"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}}
3+
{"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}}
4+
{"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}}
5+
{"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}}
6+
{"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}}
7+
{"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}}
8+
{"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}}
9+
{"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}}
10+
{"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}}
11+
{"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}}
12+
{"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}}

tests/test_util.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,40 @@ def c(x, y):
189189
assert len(optimizer.space) == 7
190190

191191

192+
def test_logs_constraint():
193+
194+
def f(x, y):
195+
return -x ** 2 - (y - 1) ** 2 + 1
196+
197+
def c(x, y):
198+
return np.array([
199+
- np.cos(x) * np.cos(y) + np.sin(x) * np.sin(y),
200+
- np.cos(x) * np.cos(-y) + np.sin(x) * np.sin(-y)
201+
])
202+
203+
constraint_lower = np.array([-np.inf, -np.inf])
204+
constraint_upper = np.array([0.6, 0.6])
205+
206+
constraint = NonlinearConstraint(c, constraint_lower, constraint_upper)
207+
208+
optimizer = BayesianOptimization(
209+
f=f,
210+
pbounds={"x": (-200, 200), "y": (-200, 200)},
211+
constraint=constraint
212+
)
213+
214+
with pytest.raises(KeyError):
215+
load_logs(optimizer, [str(test_dir / "test_logs.log")])
216+
217+
with pytest.raises(ValueError):
218+
load_logs(optimizer, [str(test_dir / "test_logs_constrained.log")])
219+
220+
load_logs(optimizer, [str(test_dir / "test_logs_multiple_constraints.log")])
221+
222+
print(optimizer.space)
223+
assert len(optimizer.space) == 12
224+
225+
192226
if __name__ == '__main__':
193227
r"""
194228
CommandLine:

0 commit comments

Comments
 (0)