Your first Bayesian optimization with Blop#
In this tutorial, you will learn the three core concepts of Blop: DOFs (the parameters you can adjust), objectives (what you want to optimize), and the Agent (which coordinates the optimization). We’ll optimize a simple mathematical function using simulated devices—the same patterns apply to real hardware.
Setup#
First, let’s import what we need and start the data infrastructure:
import logging
import time
from typing import Any
import warnings
from blop.ax import Agent, RangeDOF, Objective
from bluesky.protocols import NamedMovable, Readable, Status, Hints, HasHints, HasParent
from bluesky.run_engine import RunEngine
from bluesky_tiled_plugins import TiledWriter
from tiled.client import from_uri
from tiled.client.container import Container
from tiled.server import SimpleTiledServer
# Suppress noisy logs from httpx
logging.getLogger("httpx").setLevel(logging.WARNING)
# Suppress noisy dependency deprecations from within Ax
warnings.filterwarnings('ignore',category=FutureWarning)
[INFO 06-08 19:44:53] ax.storage.sqa_store.with_db_settings_base: Ax SQL storage initialized with SQLAlchemy 2.0.50
# Start a local Tiled server for data storage
tiled_server = SimpleTiledServer()
# Set up the Bluesky RunEngine and connect it to Tiled
RE = RunEngine({})
tiled_client = from_uri(tiled_server.uri)
tiled_writer = TiledWriter(tiled_client)
RE.subscribe(tiled_writer)
Tiled version 0.2.11
0
Creating simulated devices#
Bluesky controls devices through protocols. For this tutorial, we create simple simulated “movable” devices. In real experiments, you would use Ophyd devices or similar—the code below is just boilerplate to simulate hardware:
class AlwaysSuccessfulStatus(Status):
def add_callback(self, callback) -> None:
callback(self)
def exception(self, timeout = 0.0):
return None
@property
def done(self) -> bool:
return True
@property
def success(self) -> bool:
return True
class ReadableSignal(Readable, HasHints, HasParent):
def __init__(self, name: str) -> None:
self._name = name
self._value = 0.0
@property
def name(self) -> str:
return self._name
@property
def hints(self) -> Hints:
return {"fields": [self._name], "dimensions": [], "gridding": "rectilinear"}
@property
def parent(self) -> Any | None:
return None
def read(self):
return {self._name: {"value": self._value, "timestamp": time.time()}}
def describe(self):
return {self._name: {"source": self._name, "dtype": "number", "shape": []}}
class MovableSignal(ReadableSignal, NamedMovable):
def __init__(self, name: str, initial_value: float = 0.0) -> None:
super().__init__(name)
self._value: float = initial_value
def set(self, value: float) -> Status:
self._value = value
return AlwaysSuccessfulStatus()
Defining DOFs and objectives#
DOFs (degrees of freedom) are the parameters the optimizer can adjust. Objectives are what you want to optimize. Here we define two DOFs (x1 and x2) that can range from -5 to 5, and one objective (the Himmelblau function) that we want to minimize:
x1 = MovableSignal("x1", initial_value=0.1)
x2 = MovableSignal("x2", initial_value=0.23)
dofs = [
RangeDOF(actuator=x1, bounds=(-5, 5), parameter_type="float"),
RangeDOF(actuator=x2, bounds=(-5, 5), parameter_type="float"),
]
objectives = [
Objective(name="himmelblau_2d", minimize=True),
]
sensors = []
Writing the evaluation function#
The evaluation function computes objective values from experimental data. After each run, Blop calls this function with the run’s unique ID and the suggestions that were tried. It returns the computed objective values:
class Himmelblau2DEvaluation():
def __init__(self, tiled_client: Container):
self.tiled_client = tiled_client
def __call__(self, uid: str, suggestions: list[dict]) -> list[dict]:
run = self.tiled_client[uid]
outcomes = []
reordered_suggestions = run.start["blop_suggestions"]
x1_data = run["primary/x1"].read()
x2_data = run["primary/x2"].read()
print("[Himmelblau] evaluating suggestions: ", [s["_id"] for s in suggestions], " reordered to: ", [s["_id"] for s in reordered_suggestions])
for index, suggestion in enumerate(reordered_suggestions):
# Special key to identify a suggestion
suggestion_id = suggestion["_id"]
x1 = x1_data[index]
x2 = x2_data[index]
# Himmelblau function: has four global minima where value = 0
outcomes.append({
"himmelblau_2d": (x1 ** 2 + x2 - 11) ** 2 + (x1 + x2 ** 2 - 7) ** 2,
"_id": suggestion_id
})
return outcomes
Running the optimization#
The Agent brings everything together. Create one with your DOFs, objectives, and evaluation function, then run the optimization:
agent = Agent(
sensors=sensors,
dofs=dofs,
objectives=objectives,
evaluation_function=Himmelblau2DEvaluation(tiled_client=tiled_client),
name="simple-experiment",
description="A simple experiment optimizing the Himmelblau function",
)
RE(agent.optimize(5,n_points=8))
╭───────────────────────────────────────────────── Optimization ──────────────────────────────────────────────────╮ │ Optimizer AxOptimizer │ │ Actuators x1, x2 │ │ Sensors N/A │ │ Iterations 5 Points/iter 8 │ │ Run UID 8862e87e-8082-4ba0-971f-94c308ba9061 │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
[Himmelblau] evaluating suggestions:
[0, 1, 2, 3, 4, 5, 6, 7]
reordered to:
[0, 4, 1, 5, 3, 7, 6, 2]
[Himmelblau] evaluating suggestions:
[8, 9, 10, 11, 12, 13, 14, 15]
reordered to:
[13, 14, 10, 15, 9, 12, 8, 11]
[Himmelblau] evaluating suggestions:
[16, 17, 18, 19, 20, 21, 22, 23]
reordered to:
[16, 18, 23, 20, 21, 19, 22, 17]
[Himmelblau] evaluating suggestions:
[24, 25, 26, 27, 28, 29, 30, 31]
reordered to:
[29, 30, 25, 27, 26, 31, 24, 28]
[Himmelblau] evaluating suggestions:
[32, 33, 34, 35, 36, 37, 38, 39]
reordered to:
[34, 37, 38, 33, 36, 32, 39, 35]
[INFO 06-08 19:44:58] ax.api.client: GenerationStrategy(name='Center+Sobol+MBM:fast', nodes=[CenterGenerationNode(next_node_name='Sobol', use_existing_trials_for_initialization=True), GenerationNode(name='Sobol', generator_specs=[GeneratorSpec(generator_enum=Sobol, generator_key_override=None)], transition_criteria=[MinTrials(transition_to='MBM'), MinTrials(transition_to='MBM')], suggested_experiment_status=ExperimentStatus.INITIALIZATION, pausing_criteria=[MaxTrialsAwaitingData(threshold=5)]), GenerationNode(name='MBM', generator_specs=[GeneratorSpec(generator_enum=BoTorch, generator_key_override=None)], transition_criteria=None, suggested_experiment_status=ExperimentStatus.OPTIMIZATION, pausing_criteria=None)]) chosen based on user input and problem structure.
[INFO 06-08 19:44:58] ax.api.client: Generated new trial 0 with parameters {'x1': 0.0, 'x2': 0.0} using GenerationNode CenterOfSearchSpace.
[INFO 06-08 19:44:58] ax.api.client: Generated new trial 1 with parameters {'x1': -2.59155, 'x2': 0.987569} using GenerationNode Sobol.
[INFO 06-08 19:44:58] ax.api.client: Generated new trial 2 with parameters {'x1': 4.066084, 'x2': -4.750652} using GenerationNode Sobol.
[INFO 06-08 19:44:58] ax.api.client: Generated new trial 3 with parameters {'x1': 0.662847, 'x2': 4.515526} using GenerationNode Sobol.
[INFO 06-08 19:44:58] ax.api.client: Generated new trial 4 with parameters {'x1': -2.293787, 'x2': -0.753966} using GenerationNode Sobol.
[INFO 06-08 19:44:58] ax.api.client: Generated new trial 5 with parameters {'x1': -0.513648, 'x2': 3.665396} using GenerationNode Sobol.
[INFO 06-08 19:44:58] ax.api.client: Generated new trial 6 with parameters {'x1': 1.539112, 'x2': -2.382856} using GenerationNode Sobol.
[INFO 06-08 19:44:58] ax.api.client: Generated new trial 7 with parameters {'x1': 3.731964, 'x2': 2.149255} using GenerationNode Sobol.
[INFO 06-08 19:44:58] ax.api.client: Trial 0 marked COMPLETED.
[INFO 06-08 19:44:58] ax.api.client: Trial 4 marked COMPLETED.
[INFO 06-08 19:44:58] ax.api.client: Trial 1 marked COMPLETED.
[INFO 06-08 19:44:58] ax.api.client: Trial 5 marked COMPLETED.
[INFO 06-08 19:44:58] ax.api.client: Trial 3 marked COMPLETED.
[INFO 06-08 19:44:58] ax.api.client: Trial 7 marked COMPLETED.
[INFO 06-08 19:44:58] ax.api.client: Trial 6 marked COMPLETED.
[INFO 06-08 19:44:58] ax.api.client: Trial 2 marked COMPLETED.
[INFO 06-08 19:45:00] ax.api.client: Generated new trial 8 with parameters {'x1': 3.909665, 'x2': 4.152038} using GenerationNode MBM.
[INFO 06-08 19:45:00] ax.api.client: Generated new trial 9 with parameters {'x1': 2.983638, 'x2': 1.693101} using GenerationNode MBM.
[INFO 06-08 19:45:00] ax.api.client: Generated new trial 10 with parameters {'x1': -1.631729, 'x2': 3.696828} using GenerationNode MBM.
[INFO 06-08 19:45:00] ax.api.client: Generated new trial 11 with parameters {'x1': 4.570645, 'x2': 2.037308} using GenerationNode MBM.
[INFO 06-08 19:45:00] ax.api.client: Generated new trial 12 with parameters {'x1': 3.159051, 'x2': 4.14502} using GenerationNode MBM.
[INFO 06-08 19:45:00] ax.api.client: Generated new trial 13 with parameters {'x1': -3.938192, 'x2': 0.434307} using GenerationNode MBM.
[INFO 06-08 19:45:00] ax.api.client: Generated new trial 14 with parameters {'x1': -3.280883, 'x2': 5.0} using GenerationNode MBM.
[INFO 06-08 19:45:00] ax.api.client: Generated new trial 15 with parameters {'x1': -1.401927, 'x2': 1.78598} using GenerationNode MBM.
[INFO 06-08 19:45:01] ax.api.client: Trial 13 marked COMPLETED.
[INFO 06-08 19:45:01] ax.api.client: Trial 14 marked COMPLETED.
[INFO 06-08 19:45:01] ax.api.client: Trial 10 marked COMPLETED.
[INFO 06-08 19:45:01] ax.api.client: Trial 15 marked COMPLETED.
[INFO 06-08 19:45:01] ax.api.client: Trial 9 marked COMPLETED.
[INFO 06-08 19:45:01] ax.api.client: Trial 12 marked COMPLETED.
[INFO 06-08 19:45:01] ax.api.client: Trial 8 marked COMPLETED.
[INFO 06-08 19:45:01] ax.api.client: Trial 11 marked COMPLETED.
[INFO 06-08 19:45:03] ax.api.client: Generated new trial 16 with parameters {'x1': 3.428182, 'x2': 1.303535} using GenerationNode MBM.
[INFO 06-08 19:45:03] ax.api.client: Generated new trial 17 with parameters {'x1': 3.051406, 'x2': 2.171616} using GenerationNode MBM.
[INFO 06-08 19:45:03] ax.api.client: Generated new trial 18 with parameters {'x1': 3.497245, 'x2': 0.413395} using GenerationNode MBM.
[INFO 06-08 19:45:03] ax.api.client: Generated new trial 19 with parameters {'x1': 3.270899, 'x2': 1.779894} using GenerationNode MBM.
[INFO 06-08 19:45:03] ax.api.client: Generated new trial 20 with parameters {'x1': -0.133528, 'x2': -3.491789} using GenerationNode MBM.
[INFO 06-08 19:45:03] ax.api.client: Generated new trial 21 with parameters {'x1': 2.659967, 'x2': -0.382577} using GenerationNode MBM.
[INFO 06-08 19:45:03] ax.api.client: Generated new trial 22 with parameters {'x1': 2.422914, 'x2': 2.447399} using GenerationNode MBM.
[INFO 06-08 19:45:03] ax.api.client: Generated new trial 23 with parameters {'x1': 3.843924, 'x2': -0.732444} using GenerationNode MBM.
[INFO 06-08 19:45:03] ax.api.client: Trial 16 marked COMPLETED.
[INFO 06-08 19:45:03] ax.api.client: Trial 18 marked COMPLETED.
[INFO 06-08 19:45:03] ax.api.client: Trial 23 marked COMPLETED.
[INFO 06-08 19:45:03] ax.api.client: Trial 20 marked COMPLETED.
[INFO 06-08 19:45:03] ax.api.client: Trial 21 marked COMPLETED.
[INFO 06-08 19:45:03] ax.api.client: Trial 19 marked COMPLETED.
[INFO 06-08 19:45:03] ax.api.client: Trial 22 marked COMPLETED.
[INFO 06-08 19:45:03] ax.api.client: Trial 17 marked COMPLETED.
[INFO 06-08 19:45:05] ax.api.client: Generated new trial 24 with parameters {'x1': 3.188673, 'x2': -1.312887} using GenerationNode MBM.
[INFO 06-08 19:45:05] ax.api.client: Generated new trial 25 with parameters {'x1': -4.465638, 'x2': -3.559069} using GenerationNode MBM.
[INFO 06-08 19:45:05] ax.api.client: Generated new trial 26 with parameters {'x1': -5.0, 'x2': -5.0} using GenerationNode MBM.
[INFO 06-08 19:45:05] ax.api.client: Generated new trial 27 with parameters {'x1': -2.882559, 'x2': -5.0} using GenerationNode MBM.
[INFO 06-08 19:45:05] ax.api.client: Generated new trial 28 with parameters {'x1': 5.0, 'x2': -0.884748} using GenerationNode MBM.
[INFO 06-08 19:45:05] ax.api.client: Generated new trial 29 with parameters {'x1': -2.796722, 'x2': 2.648105} using GenerationNode MBM.
[INFO 06-08 19:45:05] ax.api.client: Generated new trial 30 with parameters {'x1': -5.0, 'x2': -2.195891} using GenerationNode MBM.
[INFO 06-08 19:45:05] ax.api.client: Generated new trial 31 with parameters {'x1': -3.596676, 'x2': -3.040158} using GenerationNode MBM.
[INFO 06-08 19:45:06] ax.api.client: Trial 29 marked COMPLETED.
[INFO 06-08 19:45:06] ax.api.client: Trial 30 marked COMPLETED.
[INFO 06-08 19:45:06] ax.api.client: Trial 25 marked COMPLETED.
[INFO 06-08 19:45:06] ax.api.client: Trial 27 marked COMPLETED.
[INFO 06-08 19:45:06] ax.api.client: Trial 26 marked COMPLETED.
[INFO 06-08 19:45:06] ax.api.client: Trial 31 marked COMPLETED.
[INFO 06-08 19:45:06] ax.api.client: Trial 24 marked COMPLETED.
[INFO 06-08 19:45:06] ax.api.client: Trial 28 marked COMPLETED.
[INFO 06-08 19:45:08] ax.api.client: Generated new trial 32 with parameters {'x1': -2.017624, 'x2': 2.787529} using GenerationNode MBM.
[INFO 06-08 19:45:08] ax.api.client: Generated new trial 33 with parameters {'x1': -4.135185, 'x2': 2.361989} using GenerationNode MBM.
[INFO 06-08 19:45:08] ax.api.client: Generated new trial 34 with parameters {'x1': -3.762604, 'x2': -3.346858} using GenerationNode MBM.
[INFO 06-08 19:45:08] ax.api.client: Generated new trial 35 with parameters {'x1': 3.327393, 'x2': -0.698863} using GenerationNode MBM.
[INFO 06-08 19:45:08] ax.api.client: Generated new trial 36 with parameters {'x1': -5.0, 'x2': 3.099192} using GenerationNode MBM.
[INFO 06-08 19:45:08] ax.api.client: Generated new trial 37 with parameters {'x1': -2.594224, 'x2': -2.652783} using GenerationNode MBM.
[INFO 06-08 19:45:08] ax.api.client: Generated new trial 38 with parameters {'x1': -3.588127, 'x2': 2.101332} using GenerationNode MBM.
[INFO 06-08 19:45:08] ax.api.client: Generated new trial 39 with parameters {'x1': 0.606864, 'x2': 2.221976} using GenerationNode MBM.
[INFO 06-08 19:45:08] ax.api.client: Trial 34 marked COMPLETED.
[INFO 06-08 19:45:08] ax.api.client: Trial 37 marked COMPLETED.
[INFO 06-08 19:45:08] ax.api.client: Trial 38 marked COMPLETED.
[INFO 06-08 19:45:08] ax.api.client: Trial 33 marked COMPLETED.
[INFO 06-08 19:45:08] ax.api.client: Trial 36 marked COMPLETED.
[INFO 06-08 19:45:08] ax.api.client: Trial 32 marked COMPLETED.
[INFO 06-08 19:45:08] ax.api.client: Trial 39 marked COMPLETED.
[INFO 06-08 19:45:08] ax.api.client: Trial 35 marked COMPLETED.
─────────────────────────────────────────── Iteration 1 / 5 (8 points) ───────────────────────────────────────────
Acquire UID 152281ac-0f7b-49f5-9668-2b22541eb584
┏━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓ ┃ Event ┃ Suggestion ID ┃ x1 ┃ x2 ┃ himmelblau_2d ┃ ┡━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩ │ 0 │ 0 │ 0 │ 0 │ 170 │ │ 1 │ 1 │ -2.59155 │ 0.987569 │ 85.1055 │ │ 2 │ 2 │ 4.06608 │ -4.75065 │ 386.137 │ │ 3 │ 3 │ 0.662847 │ 4.51553 │ 234.025 │ │ 4 │ 4 │ -2.29379 │ -0.753966 │ 118.284 │ │ 5 │ 5 │ -0.513648 │ 3.6654 │ 85.0597 │ │ 6 │ 6 │ 1.53911 │ -2.38286 │ 121.355 │ │ 7 │ 7 │ 3.73196 │ 2.14925 │ 27.5999 │ └───────┴───────────────┴───────────┴───────────┴───────────────┘
himmelblau_2d min: 27.5999 max: 386.137 mean: 153.446 (8 pts sampled)
─────────────────────────────────────────── Iteration 2 / 5 (8 points) ───────────────────────────────────────────
Acquire UID 0b696f7f-86ef-40bb-b757-05d924354768
┏━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━━┓ ┃ Event ┃ Suggestion ID ┃ x1 ┃ x2 ┃ himmelblau_2d ┃ ┡━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━━┩ │ 0 │ 10 │ -1.63173 │ 3.69683 │ 46.8848 │ │ 1 │ 11 │ 4.57064 │ 2.03731 │ 145.242 │ │ 2 │ 12 │ 3.15905 │ 4.14502 │ 187.725 │ │ 3 │ 13 │ -3.93819 │ 0.434307 │ 139.993 │ │ 4 │ 14 │ -3.28088 │ 5 │ 239.35 │ │ 5 │ 15 │ -1.40193 │ 1.78598 │ 79.7095 │ │ 6 │ 8 │ 3.90967 │ 4.15204 │ 271.388 │ │ 7 │ 9 │ 2.98364 │ 1.6931 │ 1.48584 │ └───────┴───────────────┴──────────┴──────────┴───────────────┘
himmelblau_2d min: 1.48584 max: 386.137 mean: 146.209 (16 pts sampled)
─────────────────────────────────────────── Iteration 3 / 5 (8 points) ───────────────────────────────────────────
Acquire UID 87ef7af4-f2ef-4d55-90b2-3bac0b1fb9ae
┏━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓ ┃ Event ┃ Suggestion ID ┃ x1 ┃ x2 ┃ himmelblau_2d ┃ ┡━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩ │ 0 │ 16 │ 3.42818 │ 1.30354 │ 7.73367 │ │ 1 │ 17 │ 3.05141 │ 2.17162 │ 0.821782 │ │ 2 │ 18 │ 3.49725 │ 0.413395 │ 13.8044 │ │ 3 │ 19 │ 3.2709 │ 1.77989 │ 2.50128 │ │ 4 │ 20 │ -0.133528 │ -3.49179 │ 235.09 │ │ 5 │ 21 │ 2.65997 │ -0.382577 │ 36.1384 │ │ 6 │ 22 │ 2.42291 │ 2.4474 │ 9.18924 │ │ 7 │ 23 │ 3.84392 │ -0.732444 │ 16.124 │ └───────┴───────────────┴───────────┴───────────┴───────────────┘
himmelblau_2d min: 0.821782 max: 386.137 mean: 110.864 (24 pts sampled)
─────────────────────────────────────────── Iteration 4 / 5 (8 points) ───────────────────────────────────────────
Acquire UID 78184f36-1be3-4a4a-a90b-6c98ffdec0f2
┏━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓ ┃ Event ┃ Suggestion ID ┃ x1 ┃ x2 ┃ himmelblau_2d ┃ ┡━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩ │ 0 │ 24 │ 3.18867 │ -1.31289 │ 8.96041 │ │ 1 │ 25 │ -4.46564 │ -3.55907 │ 30.4184 │ │ 2 │ 26 │ -5 │ -5 │ 250 │ │ 3 │ 27 │ -2.88256 │ -5 │ 287.686 │ │ 4 │ 28 │ 5 │ -0.884748 │ 173.491 │ │ 5 │ 29 │ -2.79672 │ 2.6481 │ 8.03328 │ │ 6 │ 30 │ -5 │ -2.19589 │ 190.862 │ │ 7 │ 31 │ -3.59668 │ -3.04016 │ 3.05263 │ └───────┴───────────────┴──────────┴───────────┴───────────────┘
himmelblau_2d min: 0.821782 max: 386.137 mean: 112.914 (32 pts sampled)
─────────────────────────────────────────── Iteration 5 / 5 (8 points) ───────────────────────────────────────────
Acquire UID 567f3ca7-5976-4b30-8481-27de0b9a9083
┏━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓ ┃ Event ┃ Suggestion ID ┃ x1 ┃ x2 ┃ himmelblau_2d ┃ ┡━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩ │ 0 │ 32 │ -2.01762 │ 2.78753 │ 18.7091 │ │ 1 │ 33 │ -4.13519 │ 2.36199 │ 102.472 │ │ 2 │ 34 │ -3.7626 │ -3.34686 │ 0.228565 │ │ 3 │ 35 │ 3.32739 │ -0.698863 │ 10.5326 │ │ 4 │ 36 │ -5 │ 3.09919 │ 298.118 │ │ 5 │ 37 │ -2.59422 │ -2.65278 │ 54.4631 │ │ 6 │ 38 │ -3.58813 │ 2.10133 │ 53.9086 │ │ 7 │ 39 │ 0.606864 │ 2.22198 │ 72.8436 │ └───────┴───────────────┴──────────┴───────────┴───────────────┘
himmelblau_2d min: 0.228565 max: 386.137 mean: 105.613 (40 pts sampled)
Summary Statistics ┏━━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━┓ ┃ Name ┃ Type ┃ Min ┃ Max ┃ Mean ┃ Std ┃ Count ┃ ┡━━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━┩ │ x1 │ param │ -5 │ 5 │ -0.0426033 │ 3.31538 │ 40 │ │ x2 │ param │ -5 │ 5 │ 0.435319 │ 2.81953 │ 40 │ │ himmelblau_2d │ outcome │ 0.228565 │ 386.137 │ 105.613 │ 104.642 │ 40 │ └───────────────┴─────────┴──────────┴─────────┴────────────┴─────────┴───────┘
────────────────────────────────────────────── Optimization Complete ──────────────────────────────────────────────
('8862e87e-8082-4ba0-971f-94c308ba9061',
'152281ac-0f7b-49f5-9668-2b22541eb584',
'0b696f7f-86ef-40bb-b757-05d924354768',
'87ef7af4-f2ef-4d55-90b2-3bac0b1fb9ae',
'78184f36-1be3-4a4a-a90b-6c98ffdec0f2',
'567f3ca7-5976-4b30-8481-27de0b9a9083')
Viewing the results#
After optimization, visualize what the Agent learned and see the best parameters found:
agent.plot_objective("x1", "x2", "himmelblau_2d")
agent.ax_client.summarize()
| trial_index | arm_name | trial_status | generation_node | himmelblau_2d | x1 | x2 | |
|---|---|---|---|---|---|---|---|
| 0 | 0 | 0_0 | COMPLETED | CenterOfSearchSpace | 170.000000 | 0.000000 | 0.000000 |
| 1 | 1 | 1_0 | COMPLETED | Sobol | 85.105479 | -2.591550 | 0.987569 |
| 2 | 2 | 2_0 | COMPLETED | Sobol | 386.136790 | 4.066084 | -4.750652 |
| 3 | 3 | 3_0 | COMPLETED | Sobol | 234.025144 | 0.662847 | 4.515526 |
| 4 | 4 | 4_0 | COMPLETED | Sobol | 118.283910 | -2.293787 | -0.753966 |
| 5 | 5 | 5_0 | COMPLETED | Sobol | 85.059719 | -0.513648 | 3.665396 |
| 6 | 6 | 6_0 | COMPLETED | Sobol | 121.355125 | 1.539112 | -2.382856 |
| 7 | 7 | 7_0 | COMPLETED | Sobol | 27.599923 | 3.731964 | 2.149255 |
| 8 | 8 | 8_0 | COMPLETED | MBM | 271.388424 | 3.909665 | 4.152038 |
| 9 | 9 | 9_0 | COMPLETED | MBM | 1.485841 | 2.983638 | 1.693101 |
| 10 | 10 | 10_0 | COMPLETED | MBM | 46.884780 | -1.631729 | 3.696828 |
| 11 | 11 | 11_0 | COMPLETED | MBM | 145.242348 | 4.570645 | 2.037308 |
| 12 | 12 | 12_0 | COMPLETED | MBM | 187.725337 | 3.159051 | 4.145020 |
| 13 | 13 | 13_0 | COMPLETED | MBM | 139.993077 | -3.938192 | 0.434307 |
| 14 | 14 | 14_0 | COMPLETED | MBM | 239.349956 | -3.280883 | 5.000000 |
| 15 | 15 | 15_0 | COMPLETED | MBM | 79.709549 | -1.401927 | 1.785980 |
| 16 | 16 | 16_0 | COMPLETED | MBM | 7.733674 | 3.428182 | 1.303535 |
| 17 | 17 | 17_0 | COMPLETED | MBM | 0.821782 | 3.051406 | 2.171616 |
| 18 | 18 | 18_0 | COMPLETED | MBM | 13.804417 | 3.497245 | 0.413395 |
| 19 | 19 | 19_0 | COMPLETED | MBM | 2.501280 | 3.270899 | 1.779894 |
| 20 | 20 | 20_0 | COMPLETED | MBM | 235.089599 | -0.133528 | -3.491789 |
| 21 | 21 | 21_0 | COMPLETED | MBM | 36.138426 | 2.659967 | -0.382577 |
| 22 | 22 | 22_0 | COMPLETED | MBM | 9.189243 | 2.422914 | 2.447399 |
| 23 | 23 | 23_0 | COMPLETED | MBM | 16.124045 | 3.843924 | -0.732444 |
| 24 | 24 | 24_0 | COMPLETED | MBM | 8.960413 | 3.188673 | -1.312887 |
| 25 | 25 | 25_0 | COMPLETED | MBM | 30.418356 | -4.465638 | -3.559069 |
| 26 | 26 | 26_0 | COMPLETED | MBM | 250.000000 | -5.000000 | -5.000000 |
| 27 | 27 | 27_0 | COMPLETED | MBM | 287.686306 | -2.882559 | -5.000000 |
| 28 | 28 | 28_0 | COMPLETED | MBM | 173.491474 | 5.000000 | -0.884748 |
| 29 | 29 | 29_0 | COMPLETED | MBM | 8.033280 | -2.796722 | 2.648105 |
| 30 | 30 | 30_0 | COMPLETED | MBM | 190.861566 | -5.000000 | -2.195891 |
| 31 | 31 | 31_0 | COMPLETED | MBM | 3.052627 | -3.596676 | -3.040158 |
| 32 | 32 | 32_0 | COMPLETED | MBM | 18.709142 | -2.017624 | 2.787529 |
| 33 | 33 | 33_0 | COMPLETED | MBM | 102.472411 | -4.135185 | 2.361989 |
| 34 | 34 | 34_0 | COMPLETED | MBM | 0.228565 | -3.762604 | -3.346858 |
| 35 | 35 | 35_0 | COMPLETED | MBM | 10.532638 | 3.327393 | -0.698863 |
| 36 | 36 | 36_0 | COMPLETED | MBM | 298.118435 | -5.000000 | 3.099192 |
| 37 | 37 | 37_0 | COMPLETED | MBM | 54.463053 | -2.594224 | -2.652783 |
| 38 | 38 | 38_0 | COMPLETED | MBM | 53.908603 | -3.588127 | 2.101332 |
| 39 | 39 | 39_0 | COMPLETED | MBM | 72.843563 | 0.606864 | 2.221976 |
The Himmelblau function has four global minima (all with value 0). The summarize output shows which one(s) the optimizer found.
What you learned#
You now understand the three core concepts of Blop:
DOFs: The parameters the optimizer adjusts (here,
x1andx2with bounds)Objectives: What you’re optimizing (here, minimizing the Himmelblau function)
Agent: Coordinates the optimization loop between Bluesky and the evaluation function
Next steps#
For a more comprehensive tutorial with multiple objectives and diagnostic tools, see Optimizing KB Mirrors.