Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/blop/ax/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ def ax_client(self) -> Client:
def checkpoint_path(self) -> str | None:
return self._optimizer.checkpoint_path

@checkpoint_path.setter
def checkpoint_path(self, value: str) -> None:
self._optimizer.checkpoint_path = value

@property
def fixed_dofs(self) -> dict[str, Any] | None:
return self._optimizer.fixed_parameters
Expand Down
5 changes: 5 additions & 0 deletions src/blop/ax/optimizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,11 @@ def checkpoint_path(self) -> str | None:
"""The file path for saving and restoring optimizer state, or ``None`` if disabled."""
return self._checkpoint_path

@checkpoint_path.setter
def checkpoint_path(self, value: str) -> None:
"""Set file path for saving and restoring optimizer state, or ``None`` if disabled."""
self._checkpoint_path = value

@property
def ax_client(self) -> Client:
"""The underlying Ax ``Client`` used for experiment management."""
Expand Down
29 changes: 29 additions & 0 deletions src/blop/tests/ax/test_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,35 @@ def test_agent_checkpoint(mock_evaluation_function, mock_acquisition_plan, tmp_p
assert len(agent.ax_client.summarize()) == 1


def test_agent_set_checkpoint_after_init(mock_evaluation_function, mock_acquisition_plan, tmp_path):
checkpoint_path = tmp_path / "checkpoint.json"
readable = ReadableSignal(name="test_readable")
agent = Agent(
sensors=[ReadableSignal(name="test_readable")],
dofs=[RangeDOF(name="x1", bounds=(0, 10), parameter_type="float")],
objectives=[Objective(name="test_objective", minimize=False)],
evaluation_function=mock_evaluation_function,
acquisition_plan=mock_acquisition_plan,
)

assert agent.checkpoint_path is None
agent.ingest([{"x1": 0.1, "test_objective": 0.2}])
agent.ax_client.configure_generation_strategy()
agent.checkpoint_path = str(checkpoint_path)
assert not checkpoint_path.exists()
agent.checkpoint()
assert checkpoint_path.exists()

agent = Agent.from_checkpoint(
str(checkpoint_path),
sensors=[readable],
actuators=[],
evaluation_function=mock_evaluation_function,
acquisition_plan=mock_acquisition_plan,
)
assert len(agent.ax_client.summarize()) == 1


def test_agent_to_optimization_problem(mock_evaluation_function):
"""Test that the agent can be converted to an optimization problem."""
movable1 = MovableSignal(name="test_movable1")
Expand Down
35 changes: 35 additions & 0 deletions src/blop/tests/ax/test_optimizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,41 @@ def test_ax_optimizer_checkpoint(tmp_path):
assert optimizer.checkpoint_path == str(checkpoint_path)


def test_ax_optimizer_set_checkpoint_after_init(tmp_path):
checkpoint_path = tmp_path / "checkpoint.json"

# Save to checkpoint
optimizer = AxOptimizer(
parameters=[
RangeParameterConfig(name="x1", bounds=(-5.0, 5.0), parameter_type="float"),
],
objective="y1",
)
assert optimizer.checkpoint_path is None
suggestions = optimizer.suggest(num_points=2)
outcomes = [
{"_id": suggestions[0]["_id"], "y1": 1.0},
{"_id": suggestions[1]["_id"], "y1": 3.0},
]
optimizer.ingest(outcomes)

with pytest.raises(ValueError, match="path is not set"):
optimizer.checkpoint()

optimizer.checkpoint_path = str(checkpoint_path)
assert not checkpoint_path.exists()
optimizer.checkpoint()
assert checkpoint_path.exists()

# Load from checkpoint
optimizer = AxOptimizer.from_checkpoint(str(checkpoint_path))
summary_df = optimizer.ax_client.summarize()
assert "x1" in summary_df.columns
assert "y1" in summary_df.columns
assert len(summary_df) == 2
assert optimizer.checkpoint_path == str(checkpoint_path)


def test_ax_optimizer_register_failures():
optimizer = AxOptimizer(
parameters=[
Expand Down
Loading