Your first Scipy optimization with Bluesky Adaptive#

In this tutorial, you will learn the three core concepts of Bluesky Adaptive: 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

from bluesky.protocols import HasHints, HasParent, Hints, NamedMovable, Readable, Status
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

from bluesky_adaptive.scipy import SCP, ScipyCFG, Objective, RangeDOF, Scipy

# Suppress noisy logs from httpx 
logging.getLogger("httpx").setLevel(logging.WARNING)
# 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)
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. Bluesky Adaptive passes it the uid returned by the acquisition plan and the suggestions that were tried. This tutorial uses the default acquisition plan, so the uid is a Bluesky run UID and blop_acquisition_order associates measurements with outcomes.

from collections.abc import Mapping, Sequence

class Himmelblau2DEvaluation:
    def __init__(self, tiled_client: Container):
        self.tiled_client = tiled_client

    def __call__(self, uid: str, suggestions: Sequence[Mapping]) -> Sequence[Mapping]:
        run = self.tiled_client[uid]
        outcomes = []
        acquisition_order = run.start["blop_acquisition_order"]
        x1_data = run["primary/x1"].read()
        x2_data = run["primary/x2"].read()

        for index, suggestion_id in enumerate(acquisition_order):
            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 = Scipy.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(10))
╭───────────────────────────────────────────────── Optimization ──────────────────────────────────────────────────╮
│ Optimizer  InteractiveOptimizer                                                                                 │
│ Actuators  x1, x2                                                                                               │
│ Sensors    N/A                                                                                                  │
│ Iterations 10                                                                                                   │
│ Run UID    4e04db0a-e485-4f53-ae95-c86d50dade7e                                                                 │
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Suggestion ID              ┃ x1                         ┃ x2                        ┃ himmelblau_2d             ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
└────────────────────────────┴────────────────────────────┴───────────────────────────┴───────────────────────────┘
┃                            ┃                            ┃                           ┃                           ┃
┃ 0                          ┃                          0 ┃                         0 ┃                       170 ┃
┡────────────────────────────╇────────────────────────────╇───────────────────────────╇───────────────────────────┩
┃                            ┃                            ┃                           ┃                           ┃
┃ 1                          ┃                      1e-08 ┃                         0 ┃                       170 ┃
┡────────────────────────────╇────────────────────────────╇───────────────────────────╇───────────────────────────┩
┃                            ┃                            ┃                           ┃                           ┃
┃ 2                          ┃                          0 ┃                     1e-08 ┃                       170 ┃
┡────────────────────────────╇────────────────────────────╇───────────────────────────╇───────────────────────────┩
┃                            ┃                            ┃                           ┃                           ┃
┃ 3                          ┃                          5 ┃                         5 ┃                       890 ┃
┡────────────────────────────╇────────────────────────────╇───────────────────────────╇───────────────────────────┩
┃                            ┃                            ┃                           ┃                           ┃
┃ 4                          ┃                          5 ┃                         5 ┃                       890 ┃
┡────────────────────────────╇────────────────────────────╇───────────────────────────╇───────────────────────────┩
──────────────────────────────────────────────── Iteration 5 / 10 ─────────────────────────────────────────────────
  himmelblau_2d  min: 170  max: 890  mean: 458
  (5 pts sampled)
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
┃                            ┃                            ┃                           ┃                           ┃
┃ 5                          ┃                          5 ┃                         5 ┃                       890 ┃
┡────────────────────────────╇────────────────────────────╇───────────────────────────╇───────────────────────────┩
┃                            ┃                            ┃                           ┃                           ┃
┃ 6                          ┃                    1.51545 ┃                   1.51545 ┃                   61.8302 ┃
┡────────────────────────────╇────────────────────────────╇───────────────────────────╇───────────────────────────┩
┃                            ┃                            ┃                           ┃                           ┃
┃ 7                          ┃                    1.51545 ┃                   1.51545 ┃                   61.8302 ┃
┡────────────────────────────╇────────────────────────────╇───────────────────────────╇───────────────────────────┩
┃                            ┃                            ┃                           ┃                           ┃
┃ 8                          ┃                    1.51545 ┃                   1.51545 ┃                   61.8302 ┃
┡────────────────────────────╇────────────────────────────╇───────────────────────────╇───────────────────────────┩
┃                            ┃                            ┃                           ┃                           ┃
┃ 9                          ┃                    3.25772 ┃                   3.25772 ┃                   55.4432 ┃
┡────────────────────────────╇────────────────────────────╇───────────────────────────╇───────────────────────────┩
──────────────────────────────────────────────── Iteration 10 / 10 ────────────────────────────────────────────────
  himmelblau_2d  min: 55.4432  max: 890  mean: 342.093
  (10 pts sampled)
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────

                          Summary Statistics                           
┏━━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┳━━━━━┳━━━━━━━━━┳━━━━━━━━━┳━━━━━━━┓
┃ Name          ┃ Type    ┃     Min ┃ Max ┃    Mean ┃     Std ┃ Count ┃
┡━━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━╇━━━━━╇━━━━━━━━━╇━━━━━━━━━╇━━━━━━━┩
│ x1            │ param   │       0 │   5 │ 2.28041 │ 2.12132 │    10 │
│ x2            │ param   │       0 │   5 │ 2.28041 │ 2.12132 │    10 │
│ himmelblau_2d │ outcome │ 55.4432 │ 890 │ 342.093 │ 381.119 │    10 │
└───────────────┴─────────┴─────────┴─────┴─────────┴─────────┴───────┘
────────────────────────────────────────────── Optimization Complete ──────────────────────────────────────────────
('4e04db0a-e485-4f53-ae95-c86d50dade7e',
 'b474c12b-e8a8-46cb-b394-5a3227ce64d4',
 'ce2cf6d3-e600-4ae8-b594-890e19c9de2d',
 'bda92c29-2a10-486b-ab6a-7d66d5bb5610',
 '494fa66e-6e73-40c7-9189-3d87d607dd2c',
 '997acc2d-f7e5-4d7f-8a08-ade9085b90b7',
 'f834eb93-8646-45f8-a609-2fc978d7a672',
 '33ee4600-9513-40f2-b80b-e0258e8847c2',
 'f799e1b6-187a-4543-8670-c7a36f476cca',
 'd52de7d8-cf1c-442f-9eb8-3f58520022b3',
 '8633fbae-61b2-4718-866c-838acc7ae06a')

Configuring the optimization#

Sometimes a default Agent optimization may not do all that you’d like. We expose a configuration object called ScipyCFG and a pure scipy interface so that the classic parameters of scipy minimize can be tweaked (and some multipoint sampling can be used).

config = ScipyCFG(dofs=dofs, objective=objectives[0], optimizer=SCP.DUAL_ANNEALING, threads=4, max_iter=2, eps=0.1)
agent = Scipy(
    sensors=sensors,
    config=config,
    evaluation_function=Himmelblau2DEvaluation(tiled_client=tiled_client),
    name="test_experiment",
)
res_uid = RE(agent.optimize(20, n_points=2))
╭───────────────────────────────────────────────── Optimization ──────────────────────────────────────────────────╮
│ Optimizer  InteractiveOptimizer                                                                                 │
│ Actuators  x1, x2                                                                                               │
│ Sensors    N/A                                                                                                  │
│ Iterations 20  Points/iter 2                                                                                    │
│ Run UID    98933927-1f2c-482a-aec9-e015ad3da675                                                                 │
╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Suggestion ID              ┃ x1                         ┃ x2                        ┃ himmelblau_2d             ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
└────────────────────────────┴────────────────────────────┴───────────────────────────┴───────────────────────────┘
┃                            ┃                            ┃                           ┃                           ┃
┃ 0                          ┃                          0 ┃                         0 ┃                       170 ┃
┡────────────────────────────╇────────────────────────────╇───────────────────────────╇───────────────────────────┩
┃                            ┃                            ┃                           ┃                           ┃
┃ 1                          ┃                    1.78425 ┃                   4.05703 ┃                   140.554 ┃
┡────────────────────────────╇────────────────────────────╇───────────────────────────╇───────────────────────────┩
┃                            ┃                            ┃                           ┃                           ┃
┃ 2                          ┃                  0.0277337 ┃                   2.30051 ┃                   78.4899 ┃
┡────────────────────────────╇────────────────────────────╇───────────────────────────╇───────────────────────────┩
┃                            ┃                            ┃                           ┃                           ┃
┃ 3                          ┃                    2.56062 ┃                   2.30051 ┃                   5.31881 ┃
┡────────────────────────────╇────────────────────────────╇───────────────────────────╇───────────────────────────┩
/home/runner/work/bluesky-adaptive/bluesky-adaptive/.pixi/envs/docs/lib/python3.13/site-packages/scipy/optimize/_dual_annealing.py:434: OptimizeWarning: Unknown solver options: max_iter
  mres = self.minimizer(self.func_wrapper.fun, x, **self.kwargs)
┃                            ┃                            ┃                           ┃                           ┃
┃ 4                          ┃                    2.56062 ┃                   4.21186 ┃                   176.953 ┃
┡────────────────────────────╇────────────────────────────╇───────────────────────────╇───────────────────────────┩
──────────────────────────────────────────────── Iteration 5 / 20 ─────────────────────────────────────────────────
  himmelblau_2d  min: 5.31881  max: 176.953  mean: 114.263
  (5 pts sampled)
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
┃                            ┃                            ┃                           ┃                           ┃
┃ 5                          ┃                    2.56062 ┃                   2.30051 ┃                   5.31881 ┃
┡────────────────────────────╇────────────────────────────╇───────────────────────────╇───────────────────────────┩
┃                            ┃                            ┃                           ┃                           ┃
┃ 6                          ┃                    2.66062 ┃                   2.30051 ┃                   3.53448 ┃
┡────────────────────────────╇────────────────────────────╇───────────────────────────╇───────────────────────────┩
┃                            ┃                            ┃                           ┃                           ┃
┃ 7                          ┃                    2.56062 ┃                   2.40051 ┃                   5.92322 ┃
┡────────────────────────────╇────────────────────────────╇───────────────────────────╇───────────────────────────┩
┃                            ┃                            ┃                           ┃                           ┃
┃ 8                          ┃                          5 ┃                  -3.74354 ┃                   249.534 ┃
┡────────────────────────────╇────────────────────────────╇───────────────────────────╇───────────────────────────┩
┃                            ┃                            ┃                           ┃                           ┃
┃ 10                         ┃                          5 ┃                  -3.64354 ┃                   234.391 ┃
┡────────────────────────────╇────────────────────────────╇───────────────────────────╇───────────────────────────┩
──────────────────────────────────────────────── Iteration 9 / 20 ─────────────────────────────────────────────────
  himmelblau_2d  min: 3.53448  max: 249.534  mean: 107.002
  (10 pts sampled)
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
┃                            ┃                            ┃                           ┃                           ┃
┃ 9                          ┃                        4.9 ┃                  -3.74354 ┃                   227.813 ┃
┡────────────────────────────╇────────────────────────────╇───────────────────────────╇───────────────────────────┩
┃                            ┃                            ┃                           ┃                           ┃
┃ 11                         ┃                    3.30038 ┃                  0.467611 ┃                   12.2468 ┃
┡────────────────────────────╇────────────────────────────╇───────────────────────────╇───────────────────────────┩
┃                            ┃                            ┃                           ┃                           ┃
┃ 12                         ┃                    3.30038 ┃                  0.567611 ┃                   11.6188 ┃
┡────────────────────────────╇────────────────────────────╇───────────────────────────╇───────────────────────────┩
┃                            ┃                            ┃                           ┃                           ┃
┃ 13                         ┃                    3.40038 ┃                  0.467611 ┃                   12.4922 ┃
┡────────────────────────────╇────────────────────────────╇───────────────────────────╇───────────────────────────┩
┃                            ┃                            ┃                           ┃                           ┃
┃ 14                         ┃                    2.75479 ┃                    1.8194 ┃                   3.40774 ┃
┡────────────────────────────╇────────────────────────────╇───────────────────────────╇───────────────────────────┩
──────────────────────────────────────────────── Iteration 12 / 20 ────────────────────────────────────────────────
  himmelblau_2d  min: 3.40774  max: 249.534  mean: 89.1731
  (15 pts sampled)
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
┃                            ┃                            ┃                           ┃                           ┃
┃ 15                         ┃                    2.75479 ┃                    1.9194 ┃                   2.54004 ┃
┡────────────────────────────╇────────────────────────────╇───────────────────────────╇───────────────────────────┩
┃                            ┃                            ┃                           ┃                           ┃
┃ 16                         ┃                    2.85479 ┃                    1.8194 ┃                   1.75965 ┃
┡────────────────────────────╇────────────────────────────╇───────────────────────────╇───────────────────────────┩
┃                            ┃                            ┃                           ┃                           ┃
┃ 17                         ┃                    3.35689 ┃                   1.94131 ┃                   4.89997 ┃
┡────────────────────────────╇────────────────────────────╇───────────────────────────╇───────────────────────────┩
┃                            ┃                            ┃                           ┃                           ┃
┃ 18                         ┃                    3.35689 ┃                   2.04131 ┃                   5.61062 ┃
┡────────────────────────────╇────────────────────────────╇───────────────────────────╇───────────────────────────┩
┃                            ┃                            ┃                           ┃                           ┃
┃ 19                         ┃                    3.45689 ┃                   1.94131 ┃                   8.41109 ┃
┡────────────────────────────╇────────────────────────────╇───────────────────────────╇───────────────────────────┩
──────────────────────────────────────────────── Iteration 15 / 20 ────────────────────────────────────────────────
  himmelblau_2d  min: 1.75965  max: 249.534  mean: 68.0409
  (20 pts sampled)
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
┃                            ┃                            ┃                           ┃                           ┃
┃ 20                         ┃                    3.04251 ┃                   1.87766 ┃                  0.204622 ┃
┡────────────────────────────╇────────────────────────────╇───────────────────────────╇───────────────────────────┩
┃                            ┃                            ┃                           ┃                           ┃
┃ 21                         ┃                    3.04251 ┃                   1.97766 ┃                 0.0571462 ┃
┡────────────────────────────╇────────────────────────────╇───────────────────────────╇───────────────────────────┩
┃                            ┃                            ┃                           ┃                           ┃
┃ 22                         ┃                    3.14251 ┃                   1.87766 ┃                  0.677184 ┃
┡────────────────────────────╇────────────────────────────╇───────────────────────────╇───────────────────────────┩
┃                            ┃                            ┃                           ┃                           ┃
┃ 23                         ┃                     2.9524 ┃                   1.96613 ┃                  0.133724 ┃
┡────────────────────────────╇────────────────────────────╇───────────────────────────╇───────────────────────────┩
┃                            ┃                            ┃                           ┃                           ┃
┃ 24                         ┃                     2.9524 ┃                   2.06613 ┃                 0.0961485 ┃
┡────────────────────────────╇────────────────────────────╇───────────────────────────╇───────────────────────────┩
──────────────────────────────────────────────── Iteration 19 / 20 ────────────────────────────────────────────────
  himmelblau_2d  min: 0.0571462  max: 249.534  mean: 54.4794
  (25 pts sampled)
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
┃                            ┃                            ┃                           ┃                           ┃
┃ 25                         ┃                     3.0524 ┃                   1.96613 ┃                 0.0869555 ┃
┡────────────────────────────╇────────────────────────────╇───────────────────────────╇───────────────────────────┩
┃                            ┃                            ┃                           ┃                           ┃
┃ 26                         ┃                    2.95604 ┃                   1.97523 ┃                  0.102429 ┃
┡────────────────────────────╇────────────────────────────╇───────────────────────────╇───────────────────────────┩

                             Summary Statistics                              
┏━━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┳━━━━━━━┓
┃ Name          ┃ Type    ┃       Min ┃     Max ┃    Mean ┃     Std ┃ Count ┃
┡━━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━╇━━━━━━━┩
│ x1            │ param   │         0 │       5 │ 2.93674 │ 1.12113 │    27 │
│ x2            │ param   │  -3.74354 │ 4.21186 │ 1.31231 │ 2.01503 │    27 │
│ himmelblau_2d │ outcome │ 0.0571462 │ 249.534 │ 50.4509 │ 84.8537 │    27 │
└───────────────┴─────────┴───────────┴─────────┴─────────┴─────────┴───────┘
────────────────────────────────────────────── Optimization Complete ──────────────────────────────────────────────

Viewing the results#

Scipy is a local optimizer so it doesn’t have internal point tracking, but we can to grab it from our datastore.

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

res_client = tiled_client[res_uid[0]]
data = res_client["primary"].read().to_dataframe()

fig, ax = plt.subplots(figsize=(12, 8))

xb, yb = np.random.uniform(-5, 5, (2, 1000))
ax.tripcolor(xb, yb, (xb**2 + yb - 11) ** 2 + (xb + yb**2 - 7) ** 2, shading="gouraud")

ps = ax.scatter(data.x1, data.x2, marker='+', c=range(len(data.x1)), cmap="plasma", s=50)
plt.colorbar(ps).set_label("sample index")
plt.title("Visualizing Scipy's traversal of Himmelblau")
Text(0.5, 1.0, "Visualizing Scipy's traversal of Himmelblau")
../_images/4d287fd35b8058c7dd1020150b3e79331dceebb688613f10f4d49d14b9f7643d.png

Seeing the sample history

data
x2 suggestion_ids himmelblau_2d x1 acquisition_uid iteration
time
1.793050e+09 0.000000 0 170.000000 0.000000 017effa8-1468-4758-93c3-ee2012bd6575 0
1.793050e+09 4.057027 1 140.554395 1.784252 38f94bc3-1cde-4660-abf7-9c235527aeb0 1
1.793050e+09 2.300509 2 78.489919 0.027734 97807c78-c19d-4177-8844-51bc5b1893dc 2
1.793050e+09 2.300509 3 5.318810 2.560618 527a1610-af28-4384-a24b-95c2bbe05d7f 3
1.793050e+09 4.211857 4 176.953074 2.560618 688a68a5-ac5d-49e7-959e-0797e48be1c8 4
1.793050e+09 2.300509 5 5.318810 2.560618 5ad9e3d0-3178-454c-83fb-765d13ccec90 5
1.793050e+09 2.300509 6 3.534480 2.660618 9c76870d-0280-434f-aea3-faf1bfe4243f 6
1.793050e+09 2.400509 7 5.923215 2.560618 9c76870d-0280-434f-aea3-faf1bfe4243f 6
1.793050e+09 -3.743542 8 249.533730 5.000000 bd50602b-be84-4f3c-843b-1b1fd516b042 7
1.793050e+09 -3.643542 10 234.390865 5.000000 ff602c73-6581-48ad-a1f5-e0d5f22ce09b 8
1.793050e+09 -3.743542 9 227.813222 4.900000 ff602c73-6581-48ad-a1f5-e0d5f22ce09b 8
1.793050e+09 0.467611 11 12.246776 3.300377 58bd887b-29e7-415a-9fa6-2ba9f3e1ecbe 9
1.793050e+09 0.567611 12 11.618799 3.300377 fc4fa361-4801-4e5e-abf6-a15a855e14c0 10
1.793050e+09 0.467611 13 12.492169 3.400377 fc4fa361-4801-4e5e-abf6-a15a855e14c0 10
1.793050e+09 1.819403 14 3.407740 2.754793 ff613496-7214-42a1-b48f-61cd82cbd912 11
1.793050e+09 1.919403 15 2.540043 2.754793 7eea6aab-01af-429a-8a25-b5879b7266a6 12
1.793050e+09 1.819403 16 1.759647 2.854793 7eea6aab-01af-429a-8a25-b5879b7266a6 12
1.793050e+09 1.941314 17 4.899971 3.356890 baa75ec2-9b2b-4f9f-8d66-2e054be53e13 13
1.793050e+09 2.041314 18 5.610623 3.356890 401316e0-abc4-43c5-b4b7-0d0eca6df7d5 14
1.793050e+09 1.941314 19 8.411085 3.456890 401316e0-abc4-43c5-b4b7-0d0eca6df7d5 14
1.793050e+09 1.877659 20 0.204622 3.042508 1751cb96-3f96-460c-b6df-7853bd6facc8 15
1.793050e+09 1.977659 21 0.057146 3.042508 b6be6ea5-1dbe-4788-8d32-1b1dce41ca92 16
1.793050e+09 1.877659 22 0.677184 3.142508 b6be6ea5-1dbe-4788-8d32-1b1dce41ca92 16
1.793050e+09 1.966129 23 0.133724 2.952399 ef7aedcc-f2a2-4ecf-b5ec-73a53054def5 17
1.793050e+09 2.066129 24 0.096148 2.952399 ceb0036e-8765-4ec2-8ad4-d851ee9cc9c0 18
1.793050e+09 1.966129 25 0.086956 3.052399 ceb0036e-8765-4ec2-8ad4-d851ee9cc9c0 18
1.793050e+09 1.975230 26 0.102429 2.956039 7d60f284-7d86-495b-875e-3bccaea708ca 19
print(agent.get_best_points())
[25, {'x1': np.float64(2.9560387532187553), 'x2': np.float64(1.9752296429882843)}, {'himmelblau_2d': np.float64(0.13372377997935608)}]

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 Bluesky Adaptive:

  • DOFs: The parameters the optimizer adjusts (here, x1 and x2 with 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.