Getting Started with the Honegumi APIο
The interactive selection grid hosted on the main page at https://honegumi.readthedocs.io/ provides a lot of value on its own. This tutorial demonstrates how to use the honegumi Python package to generate Bayesian optimization scripts on-the-fly, which has a lot of potential to be integrated with LLMs and agentic workflows. We recommend you open and run this using the Open in Colab link above.
NOTE: We also encourage you to look at the materials discovery tutorials and concept-focused docs.
Installationο
First, letβs install the honegumi package. Weβll pin both honegumi and the ax-platform dependency to help ensure compatibility. This cell may take a few moments to run.
[1]:
%pip install honegumi==0.4.0 ax-platform==0.4.3
Collecting honegumi==0.4.0
Downloading honegumi-0.4.0-py3-none-any.whl.metadata (6.5 kB)
Collecting ax-platform==0.4.3
Downloading ax_platform-0.4.3-py3-none-any.whl.metadata (11 kB)
Requirement already satisfied: numpy in /usr/local/lib/python3.11/dist-packages (from honegumi==0.4.0) (1.26.4)
Requirement already satisfied: scipy in /usr/local/lib/python3.11/dist-packages (from honegumi==0.4.0) (1.13.1)
Requirement already satisfied: pandas in /usr/local/lib/python3.11/dist-packages (from honegumi==0.4.0) (2.2.2)
Requirement already satisfied: tqdm in /usr/local/lib/python3.11/dist-packages (from honegumi==0.4.0) (4.67.1)
Requirement already satisfied: click in /usr/local/lib/python3.11/dist-packages (from honegumi==0.4.0) (8.1.8)
Requirement already satisfied: Jinja2 in /usr/local/lib/python3.11/dist-packages (from honegumi==0.4.0) (3.1.5)
Collecting black (from honegumi==0.4.0)
Downloading black-25.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl.metadata (81 kB)
ββββββββββββββββββββββββββββββββββββββββ 81.3/81.3 kB 1.6 MB/s eta 0:00:00
Requirement already satisfied: pytest in /usr/local/lib/python3.11/dist-packages (from honegumi==0.4.0) (8.3.4)
Collecting jupytext (from honegumi==0.4.0)
Downloading jupytext-1.16.7-py3-none-any.whl.metadata (13 kB)
Requirement already satisfied: pydantic in /usr/local/lib/python3.11/dist-packages (from honegumi==0.4.0) (2.10.6)
Collecting botorch==0.12.0 (from ax-platform==0.4.3)
Downloading botorch-0.12.0-py3-none-any.whl.metadata (11 kB)
Requirement already satisfied: scikit-learn in /usr/local/lib/python3.11/dist-packages (from ax-platform==0.4.3) (1.6.1)
Requirement already satisfied: ipywidgets in /usr/local/lib/python3.11/dist-packages (from ax-platform==0.4.3) (7.7.1)
Requirement already satisfied: plotly>=5.12.0 in /usr/local/lib/python3.11/dist-packages (from ax-platform==0.4.3) (5.24.1)
Collecting pyre-extensions (from ax-platform==0.4.3)
Downloading pyre_extensions-0.0.32-py3-none-any.whl.metadata (4.0 kB)
Requirement already satisfied: multipledispatch in /usr/local/lib/python3.11/dist-packages (from botorch==0.12.0->ax-platform==0.4.3) (1.0.0)
Requirement already satisfied: mpmath<=1.3,>=0.19 in /usr/local/lib/python3.11/dist-packages (from botorch==0.12.0->ax-platform==0.4.3) (1.3.0)
Requirement already satisfied: torch>=2.0.1 in /usr/local/lib/python3.11/dist-packages (from botorch==0.12.0->ax-platform==0.4.3) (2.5.1+cu124)
Collecting pyro-ppl>=1.8.4 (from botorch==0.12.0->ax-platform==0.4.3)
Downloading pyro_ppl-1.9.1-py3-none-any.whl.metadata (7.8 kB)
Requirement already satisfied: typing-extensions in /usr/local/lib/python3.11/dist-packages (from botorch==0.12.0->ax-platform==0.4.3) (4.12.2)
Collecting gpytorch==1.13 (from botorch==0.12.0->ax-platform==0.4.3)
Downloading gpytorch-1.13-py3-none-any.whl.metadata (8.0 kB)
Collecting linear-operator==0.5.3 (from botorch==0.12.0->ax-platform==0.4.3)
Downloading linear_operator-0.5.3-py3-none-any.whl.metadata (15 kB)
Collecting jaxtyping==0.2.19 (from gpytorch==1.13->botorch==0.12.0->ax-platform==0.4.3)
Downloading jaxtyping-0.2.19-py3-none-any.whl.metadata (5.7 kB)
Requirement already satisfied: typeguard>=2.13.3 in /usr/local/lib/python3.11/dist-packages (from jaxtyping==0.2.19->gpytorch==1.13->botorch==0.12.0->ax-platform==0.4.3) (4.4.2)
Requirement already satisfied: tenacity>=6.2.0 in /usr/local/lib/python3.11/dist-packages (from plotly>=5.12.0->ax-platform==0.4.3) (9.0.0)
Requirement already satisfied: packaging in /usr/local/lib/python3.11/dist-packages (from plotly>=5.12.0->ax-platform==0.4.3) (24.2)
Collecting mypy-extensions>=0.4.3 (from black->honegumi==0.4.0)
Downloading mypy_extensions-1.0.0-py3-none-any.whl.metadata (1.1 kB)
Collecting pathspec>=0.9.0 (from black->honegumi==0.4.0)
Downloading pathspec-0.12.1-py3-none-any.whl.metadata (21 kB)
Requirement already satisfied: platformdirs>=2 in /usr/local/lib/python3.11/dist-packages (from black->honegumi==0.4.0) (4.3.6)
Requirement already satisfied: ipykernel>=4.5.1 in /usr/local/lib/python3.11/dist-packages (from ipywidgets->ax-platform==0.4.3) (6.17.1)
Requirement already satisfied: ipython-genutils~=0.2.0 in /usr/local/lib/python3.11/dist-packages (from ipywidgets->ax-platform==0.4.3) (0.2.0)
Requirement already satisfied: traitlets>=4.3.1 in /usr/local/lib/python3.11/dist-packages (from ipywidgets->ax-platform==0.4.3) (5.7.1)
Requirement already satisfied: widgetsnbextension~=3.6.0 in /usr/local/lib/python3.11/dist-packages (from ipywidgets->ax-platform==0.4.3) (3.6.10)
Requirement already satisfied: ipython>=4.0.0 in /usr/local/lib/python3.11/dist-packages (from ipywidgets->ax-platform==0.4.3) (7.34.0)
Requirement already satisfied: jupyterlab-widgets>=1.0.0 in /usr/local/lib/python3.11/dist-packages (from ipywidgets->ax-platform==0.4.3) (3.0.13)
Requirement already satisfied: MarkupSafe>=2.0 in /usr/local/lib/python3.11/dist-packages (from Jinja2->honegumi==0.4.0) (3.0.2)
Requirement already satisfied: markdown-it-py>=1.0 in /usr/local/lib/python3.11/dist-packages (from jupytext->honegumi==0.4.0) (3.0.0)
Requirement already satisfied: mdit-py-plugins in /usr/local/lib/python3.11/dist-packages (from jupytext->honegumi==0.4.0) (0.4.2)
Requirement already satisfied: nbformat in /usr/local/lib/python3.11/dist-packages (from jupytext->honegumi==0.4.0) (5.10.4)
Requirement already satisfied: pyyaml in /usr/local/lib/python3.11/dist-packages (from jupytext->honegumi==0.4.0) (6.0.2)
Requirement already satisfied: python-dateutil>=2.8.2 in /usr/local/lib/python3.11/dist-packages (from pandas->honegumi==0.4.0) (2.8.2)
Requirement already satisfied: pytz>=2020.1 in /usr/local/lib/python3.11/dist-packages (from pandas->honegumi==0.4.0) (2025.1)
Requirement already satisfied: tzdata>=2022.7 in /usr/local/lib/python3.11/dist-packages (from pandas->honegumi==0.4.0) (2025.1)
Requirement already satisfied: annotated-types>=0.6.0 in /usr/local/lib/python3.11/dist-packages (from pydantic->honegumi==0.4.0) (0.7.0)
Requirement already satisfied: pydantic-core==2.27.2 in /usr/local/lib/python3.11/dist-packages (from pydantic->honegumi==0.4.0) (2.27.2)
Collecting typing-inspect (from pyre-extensions->ax-platform==0.4.3)
Downloading typing_inspect-0.9.0-py3-none-any.whl.metadata (1.5 kB)
Requirement already satisfied: iniconfig in /usr/local/lib/python3.11/dist-packages (from pytest->honegumi==0.4.0) (2.0.0)
Requirement already satisfied: pluggy<2,>=1.5 in /usr/local/lib/python3.11/dist-packages (from pytest->honegumi==0.4.0) (1.5.0)
Requirement already satisfied: joblib>=1.2.0 in /usr/local/lib/python3.11/dist-packages (from scikit-learn->ax-platform==0.4.3) (1.4.2)
Requirement already satisfied: threadpoolctl>=3.1.0 in /usr/local/lib/python3.11/dist-packages (from scikit-learn->ax-platform==0.4.3) (3.5.0)
Requirement already satisfied: debugpy>=1.0 in /usr/local/lib/python3.11/dist-packages (from ipykernel>=4.5.1->ipywidgets->ax-platform==0.4.3) (1.8.0)
Requirement already satisfied: jupyter-client>=6.1.12 in /usr/local/lib/python3.11/dist-packages (from ipykernel>=4.5.1->ipywidgets->ax-platform==0.4.3) (6.1.12)
Requirement already satisfied: matplotlib-inline>=0.1 in /usr/local/lib/python3.11/dist-packages (from ipykernel>=4.5.1->ipywidgets->ax-platform==0.4.3) (0.1.7)
Requirement already satisfied: nest-asyncio in /usr/local/lib/python3.11/dist-packages (from ipykernel>=4.5.1->ipywidgets->ax-platform==0.4.3) (1.6.0)
Requirement already satisfied: psutil in /usr/local/lib/python3.11/dist-packages (from ipykernel>=4.5.1->ipywidgets->ax-platform==0.4.3) (5.9.5)
Requirement already satisfied: pyzmq>=17 in /usr/local/lib/python3.11/dist-packages (from ipykernel>=4.5.1->ipywidgets->ax-platform==0.4.3) (24.0.1)
Requirement already satisfied: tornado>=6.1 in /usr/local/lib/python3.11/dist-packages (from ipykernel>=4.5.1->ipywidgets->ax-platform==0.4.3) (6.4.2)
Requirement already satisfied: setuptools>=18.5 in /usr/local/lib/python3.11/dist-packages (from ipython>=4.0.0->ipywidgets->ax-platform==0.4.3) (75.1.0)
Collecting jedi>=0.16 (from ipython>=4.0.0->ipywidgets->ax-platform==0.4.3)
Downloading jedi-0.19.2-py2.py3-none-any.whl.metadata (22 kB)
Requirement already satisfied: decorator in /usr/local/lib/python3.11/dist-packages (from ipython>=4.0.0->ipywidgets->ax-platform==0.4.3) (4.4.2)
Requirement already satisfied: pickleshare in /usr/local/lib/python3.11/dist-packages (from ipython>=4.0.0->ipywidgets->ax-platform==0.4.3) (0.7.5)
Requirement already satisfied: prompt-toolkit!=3.0.0,!=3.0.1,<3.1.0,>=2.0.0 in /usr/local/lib/python3.11/dist-packages (from ipython>=4.0.0->ipywidgets->ax-platform==0.4.3) (3.0.50)
Requirement already satisfied: pygments in /usr/local/lib/python3.11/dist-packages (from ipython>=4.0.0->ipywidgets->ax-platform==0.4.3) (2.18.0)
Requirement already satisfied: backcall in /usr/local/lib/python3.11/dist-packages (from ipython>=4.0.0->ipywidgets->ax-platform==0.4.3) (0.2.0)
Requirement already satisfied: pexpect>4.3 in /usr/local/lib/python3.11/dist-packages (from ipython>=4.0.0->ipywidgets->ax-platform==0.4.3) (4.9.0)
Requirement already satisfied: mdurl~=0.1 in /usr/local/lib/python3.11/dist-packages (from markdown-it-py>=1.0->jupytext->honegumi==0.4.0) (0.1.2)
Requirement already satisfied: opt-einsum>=2.3.2 in /usr/local/lib/python3.11/dist-packages (from pyro-ppl>=1.8.4->botorch==0.12.0->ax-platform==0.4.3) (3.4.0)
Collecting pyro-api>=0.1.1 (from pyro-ppl>=1.8.4->botorch==0.12.0->ax-platform==0.4.3)
Downloading pyro_api-0.1.2-py3-none-any.whl.metadata (2.5 kB)
Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.11/dist-packages (from python-dateutil>=2.8.2->pandas->honegumi==0.4.0) (1.17.0)
Requirement already satisfied: filelock in /usr/local/lib/python3.11/dist-packages (from torch>=2.0.1->botorch==0.12.0->ax-platform==0.4.3) (3.17.0)
Requirement already satisfied: networkx in /usr/local/lib/python3.11/dist-packages (from torch>=2.0.1->botorch==0.12.0->ax-platform==0.4.3) (3.4.2)
Requirement already satisfied: fsspec in /usr/local/lib/python3.11/dist-packages (from torch>=2.0.1->botorch==0.12.0->ax-platform==0.4.3) (2024.10.0)
Collecting nvidia-cuda-nvrtc-cu12==12.4.127 (from torch>=2.0.1->botorch==0.12.0->ax-platform==0.4.3)
Downloading nvidia_cuda_nvrtc_cu12-12.4.127-py3-none-manylinux2014_x86_64.whl.metadata (1.5 kB)
Collecting nvidia-cuda-runtime-cu12==12.4.127 (from torch>=2.0.1->botorch==0.12.0->ax-platform==0.4.3)
Downloading nvidia_cuda_runtime_cu12-12.4.127-py3-none-manylinux2014_x86_64.whl.metadata (1.5 kB)
Collecting nvidia-cuda-cupti-cu12==12.4.127 (from torch>=2.0.1->botorch==0.12.0->ax-platform==0.4.3)
Downloading nvidia_cuda_cupti_cu12-12.4.127-py3-none-manylinux2014_x86_64.whl.metadata (1.6 kB)
Collecting nvidia-cudnn-cu12==9.1.0.70 (from torch>=2.0.1->botorch==0.12.0->ax-platform==0.4.3)
Downloading nvidia_cudnn_cu12-9.1.0.70-py3-none-manylinux2014_x86_64.whl.metadata (1.6 kB)
Collecting nvidia-cublas-cu12==12.4.5.8 (from torch>=2.0.1->botorch==0.12.0->ax-platform==0.4.3)
Downloading nvidia_cublas_cu12-12.4.5.8-py3-none-manylinux2014_x86_64.whl.metadata (1.5 kB)
Collecting nvidia-cufft-cu12==11.2.1.3 (from torch>=2.0.1->botorch==0.12.0->ax-platform==0.4.3)
Downloading nvidia_cufft_cu12-11.2.1.3-py3-none-manylinux2014_x86_64.whl.metadata (1.5 kB)
Collecting nvidia-curand-cu12==10.3.5.147 (from torch>=2.0.1->botorch==0.12.0->ax-platform==0.4.3)
Downloading nvidia_curand_cu12-10.3.5.147-py3-none-manylinux2014_x86_64.whl.metadata (1.5 kB)
Collecting nvidia-cusolver-cu12==11.6.1.9 (from torch>=2.0.1->botorch==0.12.0->ax-platform==0.4.3)
Downloading nvidia_cusolver_cu12-11.6.1.9-py3-none-manylinux2014_x86_64.whl.metadata (1.6 kB)
Collecting nvidia-cusparse-cu12==12.3.1.170 (from torch>=2.0.1->botorch==0.12.0->ax-platform==0.4.3)
Downloading nvidia_cusparse_cu12-12.3.1.170-py3-none-manylinux2014_x86_64.whl.metadata (1.6 kB)
Requirement already satisfied: nvidia-nccl-cu12==2.21.5 in /usr/local/lib/python3.11/dist-packages (from torch>=2.0.1->botorch==0.12.0->ax-platform==0.4.3) (2.21.5)
Requirement already satisfied: nvidia-nvtx-cu12==12.4.127 in /usr/local/lib/python3.11/dist-packages (from torch>=2.0.1->botorch==0.12.0->ax-platform==0.4.3) (12.4.127)
Collecting nvidia-nvjitlink-cu12==12.4.127 (from torch>=2.0.1->botorch==0.12.0->ax-platform==0.4.3)
Downloading nvidia_nvjitlink_cu12-12.4.127-py3-none-manylinux2014_x86_64.whl.metadata (1.5 kB)
Requirement already satisfied: triton==3.1.0 in /usr/local/lib/python3.11/dist-packages (from torch>=2.0.1->botorch==0.12.0->ax-platform==0.4.3) (3.1.0)
Requirement already satisfied: sympy==1.13.1 in /usr/local/lib/python3.11/dist-packages (from torch>=2.0.1->botorch==0.12.0->ax-platform==0.4.3) (1.13.1)
Requirement already satisfied: notebook>=4.4.1 in /usr/local/lib/python3.11/dist-packages (from widgetsnbextension~=3.6.0->ipywidgets->ax-platform==0.4.3) (6.5.5)
Requirement already satisfied: fastjsonschema>=2.15 in /usr/local/lib/python3.11/dist-packages (from nbformat->jupytext->honegumi==0.4.0) (2.21.1)
Requirement already satisfied: jsonschema>=2.6 in /usr/local/lib/python3.11/dist-packages (from nbformat->jupytext->honegumi==0.4.0) (4.23.0)
Requirement already satisfied: jupyter-core!=5.0.*,>=4.12 in /usr/local/lib/python3.11/dist-packages (from nbformat->jupytext->honegumi==0.4.0) (5.7.2)
Requirement already satisfied: parso<0.9.0,>=0.8.4 in /usr/local/lib/python3.11/dist-packages (from jedi>=0.16->ipython>=4.0.0->ipywidgets->ax-platform==0.4.3) (0.8.4)
Requirement already satisfied: attrs>=22.2.0 in /usr/local/lib/python3.11/dist-packages (from jsonschema>=2.6->nbformat->jupytext->honegumi==0.4.0) (25.1.0)
Requirement already satisfied: jsonschema-specifications>=2023.03.6 in /usr/local/lib/python3.11/dist-packages (from jsonschema>=2.6->nbformat->jupytext->honegumi==0.4.0) (2024.10.1)
Requirement already satisfied: referencing>=0.28.4 in /usr/local/lib/python3.11/dist-packages (from jsonschema>=2.6->nbformat->jupytext->honegumi==0.4.0) (0.36.2)
Requirement already satisfied: rpds-py>=0.7.1 in /usr/local/lib/python3.11/dist-packages (from jsonschema>=2.6->nbformat->jupytext->honegumi==0.4.0) (0.23.1)
Requirement already satisfied: argon2-cffi in /usr/local/lib/python3.11/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets->ax-platform==0.4.3) (23.1.0)
Requirement already satisfied: nbconvert>=5 in /usr/local/lib/python3.11/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets->ax-platform==0.4.3) (7.16.6)
Requirement already satisfied: Send2Trash>=1.8.0 in /usr/local/lib/python3.11/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets->ax-platform==0.4.3) (1.8.3)
Requirement already satisfied: terminado>=0.8.3 in /usr/local/lib/python3.11/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets->ax-platform==0.4.3) (0.18.1)
Requirement already satisfied: prometheus-client in /usr/local/lib/python3.11/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets->ax-platform==0.4.3) (0.21.1)
Requirement already satisfied: nbclassic>=0.4.7 in /usr/local/lib/python3.11/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets->ax-platform==0.4.3) (1.2.0)
Requirement already satisfied: ptyprocess>=0.5 in /usr/local/lib/python3.11/dist-packages (from pexpect>4.3->ipython>=4.0.0->ipywidgets->ax-platform==0.4.3) (0.7.0)
Requirement already satisfied: wcwidth in /usr/local/lib/python3.11/dist-packages (from prompt-toolkit!=3.0.0,!=3.0.1,<3.1.0,>=2.0.0->ipython>=4.0.0->ipywidgets->ax-platform==0.4.3) (0.2.13)
Requirement already satisfied: notebook-shim>=0.2.3 in /usr/local/lib/python3.11/dist-packages (from nbclassic>=0.4.7->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets->ax-platform==0.4.3) (0.2.4)
Requirement already satisfied: beautifulsoup4 in /usr/local/lib/python3.11/dist-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets->ax-platform==0.4.3) (4.13.3)
Requirement already satisfied: bleach!=5.0.0 in /usr/local/lib/python3.11/dist-packages (from bleach[css]!=5.0.0->nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets->ax-platform==0.4.3) (6.2.0)
Requirement already satisfied: defusedxml in /usr/local/lib/python3.11/dist-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets->ax-platform==0.4.3) (0.7.1)
Requirement already satisfied: jupyterlab-pygments in /usr/local/lib/python3.11/dist-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets->ax-platform==0.4.3) (0.3.0)
Requirement already satisfied: mistune<4,>=2.0.3 in /usr/local/lib/python3.11/dist-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets->ax-platform==0.4.3) (3.1.2)
Requirement already satisfied: nbclient>=0.5.0 in /usr/local/lib/python3.11/dist-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets->ax-platform==0.4.3) (0.10.2)
Requirement already satisfied: pandocfilters>=1.4.1 in /usr/local/lib/python3.11/dist-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets->ax-platform==0.4.3) (1.5.1)
Requirement already satisfied: argon2-cffi-bindings in /usr/local/lib/python3.11/dist-packages (from argon2-cffi->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets->ax-platform==0.4.3) (21.2.0)
Requirement already satisfied: webencodings in /usr/local/lib/python3.11/dist-packages (from bleach!=5.0.0->bleach[css]!=5.0.0->nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets->ax-platform==0.4.3) (0.5.1)
Requirement already satisfied: tinycss2<1.5,>=1.1.0 in /usr/local/lib/python3.11/dist-packages (from bleach[css]!=5.0.0->nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets->ax-platform==0.4.3) (1.4.0)
Requirement already satisfied: jupyter-server<3,>=1.8 in /usr/local/lib/python3.11/dist-packages (from notebook-shim>=0.2.3->nbclassic>=0.4.7->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets->ax-platform==0.4.3) (1.24.0)
Requirement already satisfied: cffi>=1.0.1 in /usr/local/lib/python3.11/dist-packages (from argon2-cffi-bindings->argon2-cffi->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets->ax-platform==0.4.3) (1.17.1)
Requirement already satisfied: soupsieve>1.2 in /usr/local/lib/python3.11/dist-packages (from beautifulsoup4->nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets->ax-platform==0.4.3) (2.6)
Requirement already satisfied: pycparser in /usr/local/lib/python3.11/dist-packages (from cffi>=1.0.1->argon2-cffi-bindings->argon2-cffi->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets->ax-platform==0.4.3) (2.22)
Requirement already satisfied: anyio<4,>=3.1.0 in /usr/local/lib/python3.11/dist-packages (from jupyter-server<3,>=1.8->notebook-shim>=0.2.3->nbclassic>=0.4.7->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets->ax-platform==0.4.3) (3.7.1)
Requirement already satisfied: websocket-client in /usr/local/lib/python3.11/dist-packages (from jupyter-server<3,>=1.8->notebook-shim>=0.2.3->nbclassic>=0.4.7->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets->ax-platform==0.4.3) (1.8.0)
Requirement already satisfied: idna>=2.8 in /usr/local/lib/python3.11/dist-packages (from anyio<4,>=3.1.0->jupyter-server<3,>=1.8->notebook-shim>=0.2.3->nbclassic>=0.4.7->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets->ax-platform==0.4.3) (3.10)
Requirement already satisfied: sniffio>=1.1 in /usr/local/lib/python3.11/dist-packages (from anyio<4,>=3.1.0->jupyter-server<3,>=1.8->notebook-shim>=0.2.3->nbclassic>=0.4.7->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets->ax-platform==0.4.3) (1.3.1)
Downloading honegumi-0.4.0-py3-none-any.whl (23 kB)
Downloading ax_platform-0.4.3-py3-none-any.whl (1.3 MB)
ββββββββββββββββββββββββββββββββββββββββ 1.3/1.3 MB 18.7 MB/s eta 0:00:00
Downloading botorch-0.12.0-py3-none-any.whl (644 kB)
ββββββββββββββββββββββββββββββββββββββββ 644.8/644.8 kB 28.1 MB/s eta 0:00:00
Downloading gpytorch-1.13-py3-none-any.whl (277 kB)
ββββββββββββββββββββββββββββββββββββββββ 277.8/277.8 kB 15.8 MB/s eta 0:00:00
Downloading linear_operator-0.5.3-py3-none-any.whl (176 kB)
ββββββββββββββββββββββββββββββββββββββββ 176.4/176.4 kB 11.1 MB/s eta 0:00:00
Downloading jaxtyping-0.2.19-py3-none-any.whl (24 kB)
Downloading black-25.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl (1.7 MB)
ββββββββββββββββββββββββββββββββββββββββ 1.7/1.7 MB 34.1 MB/s eta 0:00:00
Downloading jupytext-1.16.7-py3-none-any.whl (154 kB)
ββββββββββββββββββββββββββββββββββββββββ 154.2/154.2 kB 9.8 MB/s eta 0:00:00
Downloading pyre_extensions-0.0.32-py3-none-any.whl (12 kB)
Downloading mypy_extensions-1.0.0-py3-none-any.whl (4.7 kB)
Downloading pathspec-0.12.1-py3-none-any.whl (31 kB)
Downloading pyro_ppl-1.9.1-py3-none-any.whl (755 kB)
ββββββββββββββββββββββββββββββββββββββββ 756.0/756.0 kB 27.3 MB/s eta 0:00:00
Downloading nvidia_cublas_cu12-12.4.5.8-py3-none-manylinux2014_x86_64.whl (363.4 MB)
ββββββββββββββββββββββββββββββββββββββββ 363.4/363.4 MB 4.4 MB/s eta 0:00:00
Downloading nvidia_cuda_cupti_cu12-12.4.127-py3-none-manylinux2014_x86_64.whl (13.8 MB)
ββββββββββββββββββββββββββββββββββββββββ 13.8/13.8 MB 58.8 MB/s eta 0:00:00
Downloading nvidia_cuda_nvrtc_cu12-12.4.127-py3-none-manylinux2014_x86_64.whl (24.6 MB)
ββββββββββββββββββββββββββββββββββββββββ 24.6/24.6 MB 53.5 MB/s eta 0:00:00
Downloading nvidia_cuda_runtime_cu12-12.4.127-py3-none-manylinux2014_x86_64.whl (883 kB)
ββββββββββββββββββββββββββββββββββββββββ 883.7/883.7 kB 35.5 MB/s eta 0:00:00
Downloading nvidia_cudnn_cu12-9.1.0.70-py3-none-manylinux2014_x86_64.whl (664.8 MB)
ββββββββββββββββββββββββββββββββββββββββ 664.8/664.8 MB 2.9 MB/s eta 0:00:00
Downloading nvidia_cufft_cu12-11.2.1.3-py3-none-manylinux2014_x86_64.whl (211.5 MB)
ββββββββββββββββββββββββββββββββββββββββ 211.5/211.5 MB 5.7 MB/s eta 0:00:00
Downloading nvidia_curand_cu12-10.3.5.147-py3-none-manylinux2014_x86_64.whl (56.3 MB)
ββββββββββββββββββββββββββββββββββββββββ 56.3/56.3 MB 9.8 MB/s eta 0:00:00
Downloading nvidia_cusolver_cu12-11.6.1.9-py3-none-manylinux2014_x86_64.whl (127.9 MB)
ββββββββββββββββββββββββββββββββββββββββ 127.9/127.9 MB 7.4 MB/s eta 0:00:00
Downloading nvidia_cusparse_cu12-12.3.1.170-py3-none-manylinux2014_x86_64.whl (207.5 MB)
ββββββββββββββββββββββββββββββββββββββββ 207.5/207.5 MB 5.3 MB/s eta 0:00:00
Downloading nvidia_nvjitlink_cu12-12.4.127-py3-none-manylinux2014_x86_64.whl (21.1 MB)
ββββββββββββββββββββββββββββββββββββββββ 21.1/21.1 MB 51.4 MB/s eta 0:00:00
Downloading typing_inspect-0.9.0-py3-none-any.whl (8.8 kB)
Downloading jedi-0.19.2-py2.py3-none-any.whl (1.6 MB)
ββββββββββββββββββββββββββββββββββββββββ 1.6/1.6 MB 45.9 MB/s eta 0:00:00
Downloading pyro_api-0.1.2-py3-none-any.whl (11 kB)
Installing collected packages: pyro-api, pathspec, nvidia-nvjitlink-cu12, nvidia-curand-cu12, nvidia-cufft-cu12, nvidia-cuda-runtime-cu12, nvidia-cuda-nvrtc-cu12, nvidia-cuda-cupti-cu12, nvidia-cublas-cu12, mypy-extensions, jedi, typing-inspect, nvidia-cusparse-cu12, nvidia-cudnn-cu12, jaxtyping, black, pyre-extensions, nvidia-cusolver-cu12, pyro-ppl, linear-operator, jupytext, gpytorch, botorch, ax-platform, honegumi
Attempting uninstall: nvidia-nvjitlink-cu12
Found existing installation: nvidia-nvjitlink-cu12 12.5.82
Uninstalling nvidia-nvjitlink-cu12-12.5.82:
Successfully uninstalled nvidia-nvjitlink-cu12-12.5.82
Attempting uninstall: nvidia-curand-cu12
Found existing installation: nvidia-curand-cu12 10.3.6.82
Uninstalling nvidia-curand-cu12-10.3.6.82:
Successfully uninstalled nvidia-curand-cu12-10.3.6.82
Attempting uninstall: nvidia-cufft-cu12
Found existing installation: nvidia-cufft-cu12 11.2.3.61
Uninstalling nvidia-cufft-cu12-11.2.3.61:
Successfully uninstalled nvidia-cufft-cu12-11.2.3.61
Attempting uninstall: nvidia-cuda-runtime-cu12
Found existing installation: nvidia-cuda-runtime-cu12 12.5.82
Uninstalling nvidia-cuda-runtime-cu12-12.5.82:
Successfully uninstalled nvidia-cuda-runtime-cu12-12.5.82
Attempting uninstall: nvidia-cuda-nvrtc-cu12
Found existing installation: nvidia-cuda-nvrtc-cu12 12.5.82
Uninstalling nvidia-cuda-nvrtc-cu12-12.5.82:
Successfully uninstalled nvidia-cuda-nvrtc-cu12-12.5.82
Attempting uninstall: nvidia-cuda-cupti-cu12
Found existing installation: nvidia-cuda-cupti-cu12 12.5.82
Uninstalling nvidia-cuda-cupti-cu12-12.5.82:
Successfully uninstalled nvidia-cuda-cupti-cu12-12.5.82
Attempting uninstall: nvidia-cublas-cu12
Found existing installation: nvidia-cublas-cu12 12.5.3.2
Uninstalling nvidia-cublas-cu12-12.5.3.2:
Successfully uninstalled nvidia-cublas-cu12-12.5.3.2
Attempting uninstall: nvidia-cusparse-cu12
Found existing installation: nvidia-cusparse-cu12 12.5.1.3
Uninstalling nvidia-cusparse-cu12-12.5.1.3:
Successfully uninstalled nvidia-cusparse-cu12-12.5.1.3
Attempting uninstall: nvidia-cudnn-cu12
Found existing installation: nvidia-cudnn-cu12 9.3.0.75
Uninstalling nvidia-cudnn-cu12-9.3.0.75:
Successfully uninstalled nvidia-cudnn-cu12-9.3.0.75
Attempting uninstall: nvidia-cusolver-cu12
Found existing installation: nvidia-cusolver-cu12 11.6.3.83
Uninstalling nvidia-cusolver-cu12-11.6.3.83:
Successfully uninstalled nvidia-cusolver-cu12-11.6.3.83
Successfully installed ax-platform-0.4.3 black-25.1.0 botorch-0.12.0 gpytorch-1.13 honegumi-0.4.0 jaxtyping-0.2.19 jedi-0.19.2 jupytext-1.16.7 linear-operator-0.5.3 mypy-extensions-1.0.0 nvidia-cublas-cu12-12.4.5.8 nvidia-cuda-cupti-cu12-12.4.127 nvidia-cuda-nvrtc-cu12-12.4.127 nvidia-cuda-runtime-cu12-12.4.127 nvidia-cudnn-cu12-9.1.0.70 nvidia-cufft-cu12-11.2.1.3 nvidia-curand-cu12-10.3.5.147 nvidia-cusolver-cu12-11.6.1.9 nvidia-cusparse-cu12-12.3.1.170 nvidia-nvjitlink-cu12-12.4.127 pathspec-0.12.1 pyre-extensions-0.0.32 pyro-api-0.1.2 pyro-ppl-1.9.1 typing-inspect-0.9.0
Setupο
Below, we import the Honegumi class and learn a bit about some of the key variables that are specific to how Honegumi interacts with the Ax Platform. Within option_rows, notice the overlap of information with the selection grid on the homepage.
[2]:
from pprint import pprint
from honegumi.core._honegumi import Honegumi
from honegumi.ax.utils import constants as cst
from honegumi.ax._ax import option_rows
pprint(option_rows)
[{'disable': False,
'display_name': 'Objective',
'hidden': False,
'name': 'objective',
'options': ['Single', 'Multi'],
'tooltip': 'Choose between <a '
"href='/docs/curriculum/concepts/sobo-vs-mobo/sobo-vs-mobo.html'>single "
'and multi-objective optimization</a> based on your project '
'needs. Single objective optimization targets one primary goal '
'(e.g. maximize the strength of a material), while '
'multi-objective optimization considers several objectives '
'simultaneously (e.g. maximize the strength of a material while '
'minimizing synthesis cost). Select the option that best aligns '
'with your optimization goals and problem complexity.'},
{'disable': False,
'display_name': 'Model Type',
'hidden': False,
'name': 'model',
'options': ['Default', 'Custom', 'Fully Bayesian'],
'tooltip': 'Choose between three surrogate model implementations: Default '
'uses a standard Gaussian process (GP), Custom enables '
'user-defined acquisition functions and hyperparameters, and <a '
"href='/docs/curriculum/concepts/freq-vs-bayes/freq-vs-bayes.html'>Fully "
'Bayesian</a> implements MCMC estimation of GP parameters. The '
'Default option provides a robust baseline performance, Custom '
'allows advanced users to tailor the optimization process, while '
'Fully Bayesian offers deeper uncertainty exploration at higher '
'computational cost. Consider your optimization needs and '
'computational resources when selecting this option.'},
{'disable': False,
'display_name': 'Task',
'hidden': False,
'name': 'task',
'options': ['Single', 'Multi'],
'tooltip': 'Choose between <a '
"href='/docs/curriculum/concepts/single-vs-multi-task/single-vs-multi-task.html'>single "
'and multi-task optimization</a> based on your experimental '
'setup. Single-task optimization focuses on one specific task, '
'while multi-task optimization leverages data from multiple '
'related tasks simultaneously (e.g. optimizing similar '
'manufacturing processes across different production sites). '
'Multi-task optimization can improve efficiency by sharing '
'information between tasks but requires related task structures. '
'Consider whether your tasks share underlying similarities when '
'making this selection.'},
{'disable': False,
'display_name': 'Categorical Parameter',
'hidden': False,
'name': 'categorical',
'options': [False, True],
'tooltip': 'Choose whether to include a categorical variable in the '
'optimization process (e.g. dark or milk chocolate chips in a '
'cookie recipe). Including categorical variables allows choice '
'parameters and their interaction with continuous variables to be '
'optimized. Note that adding categorical variables can create '
'discontinuities in the search space that are difficult to '
'optimize over. Consider the value of adding categorical '
'variables to the optimization task when selecting this option.'},
{'disable': False,
'display_name': 'Custom Generator',
'hidden': True,
'name': 'custom_gen',
'options': [False, True]},
{'disable': False,
'display_name': 'Sum Constraint',
'hidden': False,
'name': 'sum_constraint',
'options': [False, True],
'tooltip': 'Choose whether to apply a sum constraint over two or more '
'optimization variables (e.g. ensuring total allocation remains '
'within available budget). This constraint focusses generated '
'optimization trials on feasible candidates at the cost of '
'flexibility. Consider whether such a constraint reflects the '
'reality of variable interactions when selecting this option.'},
{'disable': False,
'display_name': 'Order Constraint',
'hidden': False,
'name': 'order_constraint',
'options': [False, True],
'tooltip': 'Choose whether to implement an order constraint over two or more '
'optimization variables (e.g. ensuring certain tasks precede '
'others). This constraint focusses generated optimization trials '
'on variable combinations that follow a specific order. Excluding '
'the constraint offers flexibility in variable arrangements but '
'may neglect important task sequencing or value inequality '
'considerations. Consider whether such a constraint reflects the '
'reality of variable interactions when selecting this option.'},
{'disable': False,
'display_name': 'Linear Constraint',
'hidden': False,
'name': 'linear_constraint',
'options': [False, True],
'tooltip': 'Choose whether to implement a linear constraint over two or more '
'optimization variables such that the linear combination of '
'parameter values adheres to an inequality (e.g. 0.2*x_1 + x_2 < '
'0.1). This constraint focusses generated optimization trials on '
'variable combinations that follow an enforced rule at the cost '
'of flexibility. Consider whether such a constraint reflects the '
'reality of variable interactions when selecting this option.'},
{'disable': False,
'display_name': 'Composition Constraint',
'hidden': False,
'name': 'composition_constraint',
'options': [False, True],
'tooltip': 'Choose whether to include a composition constraint over two or '
'more optimization variables such that their sum does not exceed '
'a specified total (e.g. ensuring the mole fractions of elements '
'in a composition sum to one). This constraint is particularly '
'relevant to fabrication-related tasks where the quantities of '
'components must sum to a total. Consider whether such a '
'constraint reflects the reality of variable interactions when '
'selecting this option.'},
{'disable': False,
'display_name': 'Custom Threshold',
'hidden': False,
'name': 'custom_threshold',
'options': [False, True],
'tooltip': 'Choose whether to apply custom thresholds to objectives in a '
'multi-objective optimization problem (e.g. a minimum acceptable '
'strength requirement for a material). Setting a threshold on an '
'objective guides the optimization algorithm to prioritize '
'solutions that meet or exceed these criteria. Excluding '
'thresholds enables greater exploration of the design space, but '
'may produce sub-optimal solutions. Consider whether threshold '
'values reflect the reality or expectations of your optimization '
'task when selection this option.'},
{'disable': False,
'display_name': 'Existing Data',
'hidden': False,
'name': 'existing_data',
'options': [False, True],
'tooltip': 'Choose whether to fit the surrogate model to previous data '
'before starting the optimization process. Including historical '
'data may give your model a better starting place and potentially '
'speed up convergence. Conversely, excluding existing data means '
'starting the optimization from scratch, which might be preferred '
'in scenarios where historical data could introduce bias or noise '
'into the optimization process. Consider the relevance and '
'reliability of your existing data when making your selection.'},
{'disable': False,
'display_name': 'Synchrony',
'hidden': False,
'name': 'synchrony',
'options': ['Single', 'Batch'],
'tooltip': 'Choose whether to perform <a '
"href='curriculum/concepts/batch/single-vs-batch.md'>single or "
'batch evaluations</a> for your Bayesian optimization campaign. '
'Single evaluations analyze one candidate solution at a time, '
'offering precise control and adaptability after each trial at '
'the expense of more compute time. Batch evaluations, however, '
'process several solutions in parallel, significantly reducing '
'the number of optimization cycles but potentially diluting the '
'specificity of adjustments. Batch evaluation is helpful in '
'scenarios where it is advantageous to test several solutions '
'simultaneously. Consider the nature of your evaluation tool when '
'selecting between the two options.'},
{'disable': False,
'display_name': 'Visualize Results',
'hidden': False,
'name': 'visualize',
'options': [False, True],
'tooltip': 'Choose whether to include visualization tools for tracking '
'optimization progress. The default visualizations display key '
'performance metrics like optimization traces and model '
'uncertainty (e.g. objective value convergence over time). '
'Including visualizations helps monitor optimization progress and '
'identify potential issues, but may add minor computational '
'overhead. Consider whether real-time performance tracking would '
'benefit your optimization workflow when selecting this option.'}]
We also define certain constants that we reuse throughout the codebase.
[3]:
dir(cst)
[3]:
['CATEGORICAL_KEY',
'COMPOSITIONAL_CONSTRAINT_KEY',
'CONTEXTUAL_VAR_KEY',
'CUSTOM_GEN_KEY',
'CUSTOM_KEY',
'CUSTOM_THRESHOLD_KEY',
'DUMMY_KEY',
'EXISTING_DATA_KEY',
'FEATURIZATION_KEY',
'FIDELITY_OPT_KEY',
'FULLYBAYESIAN_KEY',
'LINEAR_CONSTRAINT_KEY',
'MODEL_KWARGS_KEY',
'MODEL_OPT_KEY',
'OBJECTIVE_OPT_KEY',
'ORDER_CONSTRAINT_KEY',
'PREDEFINED_CANDIDATES_KEY',
'SUM_CONSTRAINT_KEY',
'SYNCHRONY_OPT_KEY',
'TASK_OPT_KEY',
'VISUALIZE_KEY',
'__builtins__',
'__cached__',
'__doc__',
'__file__',
'__loader__',
'__name__',
'__package__',
'__spec__']
For example, the OBJECTIVE_OPT_KEY and LINEAR_CONSTRAINT_KEY.
[4]:
print(cst.OBJECTIVE_OPT_KEY)
print(cst.LINEAR_CONSTRAINT_KEY)
objective
linear_constraint
Weβll also need a few of the files that define our template. main.py.jinja encodes the logic of the Ax Platform API. honegumi.html.jinja encodes the logic and the functionality behind the interactive selection grid on the website. Weβll describe these in more detail at the end of this tutorial.
[5]:
from os import path
import honegumi
script_template_dir = honegumi.ax.__path__[0]
core_template_dir = honegumi.core.__path__[0]
script_template_name = "main.py.jinja"
core_template_name = "honegumi.html.jinja"
print(path.join(script_template_dir, script_template_name))
print(path.join(core_template_dir, core_template_name))
/usr/local/lib/python3.11/dist-packages/honegumi/ax/main.py.jinja
/usr/local/lib/python3.11/dist-packages/honegumi/core/honegumi.html.jinja
Basic Usageο
After we create an instance of the Honegumi class, we can use a pydantic model called OptionsModel to store our βgrid selectionβ. We can set whichever arguments we like, and the rest will be set to default values, as shown in the model_dump() output below This also shows you what the allowed parameters are. Notice that these keys are the same keys defined in cst.
In this case, weβll create a multi-objective optimization script (objective="multi") which incorporates existing data thatβs already been collected (existing_data=True). For illustration, we also set linear_constraint=False, but this is the default anyway.
[6]:
hg = Honegumi(
cst,
option_rows,
script_template_dir=script_template_dir,
core_template_dir=core_template_dir,
script_template_name=script_template_name,
core_template_name=core_template_name,
)
options_model = hg.OptionsModel(
objective="multi", linear_constraint=True, existing_data=True
)
pprint(options_model.model_dump())
{'categorical': False,
'composition_constraint': False,
'custom_gen': False,
'custom_threshold': False,
'existing_data': True,
'linear_constraint': True,
'model': 'Default',
'objective': 'multi',
'order_constraint': False,
'sum_constraint': False,
'synchrony': 'Single',
'task': 'Single',
'visualize': False}
Next, we can use our pydantic model that encodes our configuration to generate the optimization script.
[7]:
result = hg.generate(options_model)
print(result)
import numpy as np
import pandas as pd
from ax.service.ax_client import AxClient, ObjectiveProperties
obj1_name = "branin"
def branin(x1, x2):
y = float(
(x2 - 5.1 / (4 * np.pi**2) * x1**2 + 5.0 / np.pi * x1 - 6.0) ** 2
+ 10 * (1 - 1.0 / (8 * np.pi)) * np.cos(x1)
+ 10
)
return y
# Define the training data
X_train = pd.DataFrame(
[
{"x1": -3.0, "x2": 5.0},
{"x1": 0.0, "x2": 6.2},
{"x1": 5.9, "x2": 2.0},
{"x1": 1.5, "x2": 2.0},
{"x1": 1.0, "x2": 9.0},
]
)
# Define y_train (normally the values would be supplied directly instead of calculating here)
y_train = [branin(row["x1"], row["x2"]) for _, row in X_train.iterrows()]
# See https://youtu.be/4tnaL9ts6CQ for simple human-in-the-loop BO instructions
# Define the number of training examples
n_train = len(X_train)
ax_client = AxClient()
ax_client.create_experiment(
parameters=[
{"name": "x1", "type": "range", "bounds": [-5.0, 10.0]},
{"name": "x2", "type": "range", "bounds": [0.0, 10.0]},
],
objectives={
obj1_name: ObjectiveProperties(minimize=True),
},
parameter_constraints=[
"1.0*x1 + 0.5*x2 <= 15.0", # example of a linear constraint. Note the lack of space around the asterisks
],
)
# Add existing data to the AxClient
for i in range(n_train):
parameterization = X_train.iloc[i].to_dict()
ax_client.attach_trial(parameterization)
ax_client.complete_trial(trial_index=i, raw_data=y_train[i])
for i in range(19):
parameterization, trial_index = ax_client.get_next_trial()
# extract parameters
x1 = parameterization["x1"]
x2 = parameterization["x2"]
results = branin(x1, x2)
ax_client.complete_trial(trial_index=trial_index, raw_data=results)
Execution and Resultsο
Now, letβs try running this script. After writing the script to a file, weβll import the module so that it runs the code and retains the variables in the Colab runtime. More specifically, we use importlib.reload(...) so that if we re-run the cell, the code will run again. This is just for the sake of demonstration within a Colab notebook.
[8]:
script_name = "multi_objective_existing_data.py"
with open(script_name, "w") as f:
f.write(result)
[10]:
import importlib
if "multi_objective_existing_data" in globals():
importlib.reload(multi_objective_existing_data)
else:
import multi_objective_existing_data
[WARNING 03-01 12:30:02] ax.service.utils.with_db_settings_base: Ax currently requires a sqlalchemy version below 2.0. This will be addressed in a future release. Disabling SQL storage in Ax for now, if you would like to use SQL storage please install Ax with mysql extras via `pip install ax-platform[mysql]`.
[INFO 03-01 12:30:02] ax.service.ax_client: Starting optimization with verbose logging. To disable logging, set the `verbose_logging` argument to `False`. Note that float values in the logs are rounded to 6 decimal points.
[INFO 03-01 12:30:02] ax.service.utils.instantiation: Inferred value type of ParameterType.FLOAT for parameter x1. If that is not the expected value type, you can explicitly specify 'value_type' ('int', 'float', 'bool' or 'str') in parameter dict.
[INFO 03-01 12:30:02] ax.service.utils.instantiation: Inferred value type of ParameterType.FLOAT for parameter x2. If that is not the expected value type, you can explicitly specify 'value_type' ('int', 'float', 'bool' or 'str') in parameter dict.
[INFO 03-01 12:30:02] ax.service.utils.instantiation: Created search space: SearchSpace(parameters=[RangeParameter(name='x1', parameter_type=FLOAT, range=[-5.0, 10.0]), RangeParameter(name='x2', parameter_type=FLOAT, range=[0.0, 10.0])], parameter_constraints=[ParameterConstraint(1.0*x1 + 0.5*x2 <= 15.0)]).
[INFO 03-01 12:30:02] ax.modelbridge.dispatch_utils: Using Models.BOTORCH_MODULAR since there is at least one ordered parameter and there are no unordered categorical parameters.
[INFO 03-01 12:30:02] ax.modelbridge.dispatch_utils: Calculating the number of remaining initialization trials based on num_initialization_trials=None max_initialization_trials=None num_tunable_parameters=2 num_trials=None use_batch_trials=False
[INFO 03-01 12:30:02] ax.modelbridge.dispatch_utils: calculated num_initialization_trials=5
[INFO 03-01 12:30:02] ax.modelbridge.dispatch_utils: num_completed_initialization_trials=0 num_remaining_initialization_trials=5
[INFO 03-01 12:30:02] ax.modelbridge.dispatch_utils: `verbose`, `disable_progbar`, and `jit_compile` are not yet supported when using `choose_generation_strategy` with ModularBoTorchModel, dropping these arguments.
[INFO 03-01 12:30:02] ax.modelbridge.dispatch_utils: Using Bayesian Optimization generation strategy: GenerationStrategy(name='Sobol+BoTorch', steps=[Sobol for 5 trials, BoTorch for subsequent trials]). Iterations after 5 will take longer to generate due to model-fitting.
[INFO 03-01 12:30:02] ax.core.experiment: Attached custom parameterizations [{'x1': -3.0, 'x2': 5.0}] as trial 0.
[INFO 03-01 12:30:02] ax.service.ax_client: Completed trial 0 with data: {'branin': (48.620235, None)}.
[INFO 03-01 12:30:02] ax.core.experiment: Attached custom parameterizations [{'x1': 0.0, 'x2': 6.2}] as trial 1.
[INFO 03-01 12:30:02] ax.service.ax_client: Completed trial 1 with data: {'branin': (19.642113, None)}.
[INFO 03-01 12:30:02] ax.core.experiment: Attached custom parameterizations [{'x1': 5.9, 'x2': 2.0}] as trial 2.
[INFO 03-01 12:30:02] ax.service.ax_client: Completed trial 2 with data: {'branin': (19.70361, None)}.
[INFO 03-01 12:30:02] ax.core.experiment: Attached custom parameterizations [{'x1': 1.5, 'x2': 2.0}] as trial 3.
[INFO 03-01 12:30:02] ax.service.ax_client: Completed trial 3 with data: {'branin': (14.301934, None)}.
[INFO 03-01 12:30:02] ax.core.experiment: Attached custom parameterizations [{'x1': 1.0, 'x2': 9.0}] as trial 4.
[INFO 03-01 12:30:02] ax.service.ax_client: Completed trial 4 with data: {'branin': (35.100744, None)}.
/usr/local/lib/python3.11/dist-packages/ax/modelbridge/cross_validation.py:463: UserWarning: Encountered exception in computing model fit quality: RandomModelBridge does not support prediction.
warn("Encountered exception in computing model fit quality: " + str(e))
[INFO 03-01 12:30:02] ax.service.ax_client: Generated new trial 5 with parameters {'x1': -3.674915, 'x2': 4.205466} using model Sobol.
[INFO 03-01 12:30:02] ax.service.ax_client: Completed trial 5 with data: {'branin': (89.865537, None)}.
/usr/local/lib/python3.11/dist-packages/ax/modelbridge/cross_validation.py:463: UserWarning: Encountered exception in computing model fit quality: RandomModelBridge does not support prediction.
warn("Encountered exception in computing model fit quality: " + str(e))
[INFO 03-01 12:30:02] ax.service.ax_client: Generated new trial 6 with parameters {'x1': 9.256743, 'x2': 5.934658} using model Sobol.
[INFO 03-01 12:30:02] ax.service.ax_client: Completed trial 6 with data: {'branin': (13.476944, None)}.
/usr/local/lib/python3.11/dist-packages/ax/modelbridge/cross_validation.py:463: UserWarning: Encountered exception in computing model fit quality: RandomModelBridge does not support prediction.
warn("Encountered exception in computing model fit quality: " + str(e))
[INFO 03-01 12:30:02] ax.service.ax_client: Generated new trial 7 with parameters {'x1': 2.920666, 'x2': 0.91563} using model Sobol.
[INFO 03-01 12:30:02] ax.service.ax_client: Completed trial 7 with data: {'branin': (2.99661, None)}.
/usr/local/lib/python3.11/dist-packages/ax/modelbridge/cross_validation.py:463: UserWarning: Encountered exception in computing model fit quality: RandomModelBridge does not support prediction.
warn("Encountered exception in computing model fit quality: " + str(e))
[INFO 03-01 12:30:02] ax.service.ax_client: Generated new trial 8 with parameters {'x1': 0.793487, 'x2': 9.187776} using model Sobol.
[INFO 03-01 12:30:02] ax.service.ax_client: Completed trial 8 with data: {'branin': (35.825466, None)}.
/usr/local/lib/python3.11/dist-packages/ax/modelbridge/cross_validation.py:463: UserWarning: Encountered exception in computing model fit quality: RandomModelBridge does not support prediction.
warn("Encountered exception in computing model fit quality: " + str(e))
[INFO 03-01 12:30:02] ax.service.ax_client: Generated new trial 9 with parameters {'x1': -1.103145, 'x2': 1.505024} using model Sobol.
[INFO 03-01 12:30:02] ax.service.ax_client: Completed trial 9 with data: {'branin': (55.389651, None)}.
[INFO 03-01 12:30:12] ax.service.ax_client: Generated new trial 10 with parameters {'x1': 3.377855, 'x2': 1.667043} using model BoTorch.
[INFO 03-01 12:30:12] ax.service.ax_client: Completed trial 10 with data: {'branin': (0.850327, None)}.
[INFO 03-01 12:30:20] ax.service.ax_client: Generated new trial 11 with parameters {'x1': -3.642577, 'x2': 6.86777} using model BoTorch.
[INFO 03-01 12:30:20] ax.service.ax_client: Completed trial 11 with data: {'branin': (45.715847, None)}.
[INFO 03-01 12:30:29] ax.service.ax_client: Generated new trial 12 with parameters {'x1': 2.767847, 'x2': 2.899122} using model BoTorch.
[INFO 03-01 12:30:29] ax.service.ax_client: Completed trial 12 with data: {'branin': (1.159734, None)}.
[INFO 03-01 12:30:38] ax.service.ax_client: Generated new trial 13 with parameters {'x1': -1.72128, 'x2': 7.015582} using model BoTorch.
[INFO 03-01 12:30:38] ax.service.ax_client: Completed trial 13 with data: {'branin': (12.99854, None)}.
[INFO 03-01 12:30:47] ax.service.ax_client: Generated new trial 14 with parameters {'x1': 4.193669, 'x2': 4.345781} using model BoTorch.
[INFO 03-01 12:30:47] ax.service.ax_client: Completed trial 14 with data: {'branin': (12.792524, None)}.
[INFO 03-01 12:30:56] ax.service.ax_client: Generated new trial 15 with parameters {'x1': 7.228182, 'x2': 6.251733} using model BoTorch.
[INFO 03-01 12:30:56] ax.service.ax_client: Completed trial 15 with data: {'branin': (40.687321, None)}.
[INFO 03-01 12:31:05] ax.service.ax_client: Generated new trial 16 with parameters {'x1': 10.0, 'x2': 3.342477} using model BoTorch.
[INFO 03-01 12:31:05] ax.service.ax_client: Completed trial 16 with data: {'branin': (2.058415, None)}.
[INFO 03-01 12:31:13] ax.service.ax_client: Generated new trial 17 with parameters {'x1': 9.192263, 'x2': 0.507102} using model BoTorch.
[INFO 03-01 12:31:13] ax.service.ax_client: Completed trial 17 with data: {'branin': (3.820236, None)}.
[INFO 03-01 12:31:20] ax.service.ax_client: Generated new trial 18 with parameters {'x1': 8.951354, 'x2': 2.570459} using model BoTorch.
[INFO 03-01 12:31:20] ax.service.ax_client: Completed trial 18 with data: {'branin': (1.671016, None)}.
[INFO 03-01 12:31:30] ax.service.ax_client: Generated new trial 19 with parameters {'x1': 10.0, 'x2': 1.479869} using model BoTorch.
[INFO 03-01 12:31:30] ax.service.ax_client: Completed trial 19 with data: {'branin': (4.262935, None)}.
[INFO 03-01 12:31:39] ax.service.ax_client: Generated new trial 20 with parameters {'x1': 10.0, 'x2': 10.0} using model BoTorch.
[INFO 03-01 12:31:39] ax.service.ax_client: Completed trial 20 with data: {'branin': (50.901757, None)}.
[INFO 03-01 12:31:48] ax.service.ax_client: Generated new trial 21 with parameters {'x1': 4.256443, 'x2': 0.0} using model BoTorch.
[INFO 03-01 12:31:48] ax.service.ax_client: Completed trial 21 with data: {'branin': (8.22486, None)}.
[INFO 03-01 12:31:57] ax.service.ax_client: Generated new trial 22 with parameters {'x1': 9.449373, 'x2': 2.755402} using model BoTorch.
[INFO 03-01 12:31:57] ax.service.ax_client: Completed trial 22 with data: {'branin': (0.468172, None)}.
[INFO 03-01 12:32:06] ax.service.ax_client: Generated new trial 23 with parameters {'x1': 7.731696, 'x2': 0.0} using model BoTorch.
[INFO 03-01 12:32:06] ax.service.ax_client: Completed trial 23 with data: {'branin': (13.179622, None)}.
We can check the new variables that have been defined, again, done in this way just for demonstration purposes.
[11]:
dir(multi_objective_existing_data)
[11]:
['AxClient',
'ObjectiveProperties',
'X_train',
'__builtins__',
'__cached__',
'__doc__',
'__file__',
'__loader__',
'__name__',
'__package__',
'__spec__',
'ax_client',
'branin',
'i',
'n_train',
'np',
'obj1_name',
'parameterization',
'pd',
'results',
'trial_index',
'x1',
'x2',
'y_train']
Using the ax_client object, we can check the best parameters that were found as a result of the optimization campaign.
[12]:
from multi_objective_existing_data import ax_client
ax_client.get_best_parameters()
[12]:
({'x1': 9.449373107719564, 'x2': 2.7554017508292756},
({'branin': 0.3066354712271675}, {'branin': {'branin': 1.158551057602462}}))
Finally, we can visualize the optimization performance vs. the number of iterations using a built-in function, but first we need to adjust Colab a bit to allow us to render the plot.
[13]:
from ax.utils.notebook.plotting import init_notebook_plotting, render
import plotly.io as pio
init_notebook_plotting()
pio.renderers.default = "colab"
[INFO 03-01 12:32:07] ax.utils.notebook.plotting: Injecting Plotly library into cell. Do not overwrite or delete cell.
[INFO 03-01 12:32:07] ax.utils.notebook.plotting: Please see
(https://ax.dev/tutorials/visualizations.html#Fix-for-plots-that-are-not-rendering)
if visualizations are not rendering.
[14]:
from ax.utils.measurement.synthetic_functions import branin
render(
ax_client.get_optimization_trace(objective_optimum=branin.fmin)
)
# objective_optimum is optional, shown here because we know the true optimum
If you have questions or feedback, please reach out by opening a new GitHub discussion. If you find any bugs or have a suggestion for a new feature, please open an issue. Weβre especially interested to see how the honegumi Python package could be integrated with LLM APIs, workflow orchestrators, and agentic
workflows for materials optimization. See below if youβd like to learn more about how Honegumi works under the hood.
Under the hoodο
Perhaps the most important file is main.py.jinja, which encodes all of the logic for generating the scripts. The file is printed below. For more information about the templating language, see our Colab tutorial: A Gentle Introduction to Jinja2.
[15]:
from os import path
template_fpath = path.join(script_template_dir, "main.py.jinja")
with open(template_fpath, 'r') as f:
print(f.read())
{%- if existing_data or visualize %}
import numpy as np
import pandas as pd
from ax.service.ax_client import AxClient, ObjectiveProperties
{% if visualize %}import matplotlib.pyplot as plt{% endif %}
{% else %}
import numpy as np
from ax.service.ax_client import AxClient, ObjectiveProperties
{% endif %}
{# List of expected models #}
{% set expected_models = ["Default", "Custom", "Fully Bayesian"] %}
{# Check if model is in the list of expected models #}
{% if model not in expected_models %}
{{ 0/0 }}
{% endif %}
{% if custom_gen -%}
from ax.modelbridge.factory import Models
from ax.modelbridge.generation_strategy import GenerationStep, GenerationStrategy
{%- endif %}
{% if model == "Custom" -%}
from botorch.acquisition import UpperConfidenceBound
{%- endif %}
{% if task == "Multi" -%}
from ax.modelbridge.registry import Specified_Task_ST_MTGP_trans
from ax.core.observation import ObservationFeatures
{%- endif %}
obj1_name = "branin"
{% if objective == "Multi" -%}
obj2_name = "branin_swapped"
{%- endif %}
def branin{% if composition_constraint %}3{% endif %}{% if objective == "Multi" %}_moo{% endif %}{% if task == "Multi" %}_mt{% endif %}(x1, x2{% if composition_constraint %}, x3{% endif %}{% if categorical %}, c1{% endif %}{% if task == "Multi" %}, task{% endif %}):
y = float(
(x2 - 5.1 / (4 * np.pi**2) * x1**2 + 5.0 / np.pi * x1 - 6.0) ** 2
+ 10 * (1 - 1.0 / (8 * np.pi)) * np.cos(x1)
+ 10
)
{% if task == "Multi" %}
# if multi-task, add a penalty based on task
penalty_lookup = {"A": 1.0, "B": 1.1 + x1 + 2*x2}
y += penalty_lookup[task]
{% endif %}
{% if composition_constraint -%}
# Contrived way to incorporate x3 into the objective
y = y * (1 + 0.1 * x1 * x2 * x3)
{%- endif %}
{% if categorical %}
# add a made-up penalty based on category
penalty_lookup = {"A": 1.0, "B": 0.0, "C": 2.0}
y += penalty_lookup[c1]
{% endif %}
{% if objective == "Multi" -%}
# second objective has x1 and x2 swapped
y2 = float(
(x1 - 5.1 / (4 * np.pi**2) * x2**2 + 5.0 / np.pi * x2 - 6.0) ** 2
+ 10 * (1 - 1.0 / (8 * np.pi)) * np.cos(x2)
+ 10
)
{% if task == "Multi" %}
# if multi-task, add a penalty based on task for second objective
penalty_lookup_2 = {"A": 0.8, "B": 0.9 + 2*x1 + x2}
y2 += penalty_lookup_2[task]
{% endif %}
{% if composition_constraint -%}
# Contrived way to incorporate x3 into the second objective
y2 = y2 * (1 - 0.1 * x1 * x2 * x3)
{%- endif %}
{% if categorical %}
# add a made-up penalty based on category
penalty_lookup = {"A": 0.0, "B": 2.0, "C": 1.0}
y2 += penalty_lookup[c1]
{% endif %}
return {obj1_name: y, obj2_name: y2}
{% else %} {# single objective #}
return y
{%- endif %}
{% set objective_function = "branin" %}
{% if composition_constraint -%}
{% set objective_function = objective_function + "3" %}
{% endif %}
{# Set the objective function based on the objective #}
{% if objective == "Multi" -%}
{% set objective_function = objective_function + "_moo" %}
{%- endif %}
{% if task == "Multi" %}
{% set objective_function = objective_function + "_mt" %}
{% endif %}
{# add MOO to FULLYBAYESIAN if multi-objective #}
{% if model == "Fully Bayesian" and objective == "Multi" -%}
{% set model_name = "FULLYBAYESIANMOO" %}
{% elif model == "Fully Bayesian" and objective != "Multi" -%}
{% set model_name = "FULLYBAYESIAN" %}
{% else %}
{% set model_name = "BOTORCH_MODULAR" %}
{%- endif %}
{% if composition_constraint %}
# Define total for compositional constraint, where x1 + x2 + x3 == total
total = 10.0
{% endif %}
{% if existing_data -%} {# categorical inline/repeated because will be clearer to readers #}
# Define the training data
{% if composition_constraint %}
# note that for this training data, the compositional constraint is satisfied
{% endif %}
{% if order_constraint %}
# note that for this training data, the order constraint is satisfied
{% endif %} {# TODO: REVIEW: consider how to incorporate out of design with the above scheme. Probably add an additional point that is for sure out of design and warn user if there are points like this? #}
{# Set some shorthand variables to make X_train more readable #}
{% set mt = task == "Multi"%}
{% set comp = composition_constraint %}
{% set cat = categorical %}
{% set ord = order_constraint %}
{# Note the lack of comma after x2, and the presence of a comma before the x3 #}
X_train = pd.DataFrame([
{
"x1": {% if comp %}4.0{% else %}-3.0{% endif %},
"x2": 5.0
{% if mt %}, "task": "A"{% endif %}
{% if comp %},"x3": 1.0{% endif %}
{% if cat %},"c1": "A"{% endif %}
},
{
"x1": 0.0,
"x2": 6.2
{% if mt %}, "task": "B"{% endif %}
{% if comp %},"x3": 3.8{% endif %}
{% if cat %},"c1": "B"{% endif %}
},
{
"x1": {% if ord %}2.1{% else %}5.9{% endif %},
"x2": {% if ord %}5.9{% else %}2.0{% endif %}
{% if mt %}, "task": "A"{% endif %}
{% if comp %},"x3": 2.0{% endif %}
{% if cat %},"c1": "C"{% endif %}
},
{
"x1": 1.5,
"x2": 2.0
{% if mt %}, "task": "B"{% endif %}
{% if comp %},"x3": 6.5{% endif %}
{% if cat %},"c1": "A"{% endif %}
},
{
"x1": 1.0,
"x2": 9.0
{% if mt %}, "task": "A"{% endif %}
{% if comp %},"x3": 0.0{% endif %}
{% if cat %},"c1": "B"{% endif %}
}
])
# Define y_train (normally the values would be supplied directly instead of calculating here)
y_train = [
{{ objective_function }}(
row["x1"],
row["x2"]
{% if composition_constraint %}, row["x3"]{% endif %}
{% if categorical %}, row["c1"]{% endif %}
{% if task == "Multi" %}, row["task"]{% endif %}
)
for _, row in X_train.iterrows()
]
# See https://youtu.be/4tnaL9ts6CQ for simple human-in-the-loop BO instructions
# Define the number of training examples
n_train = len(X_train)
{%- endif %}
{# Logic around the number of iterations #}
{# A reasonable default for initialization points is 2 * number of parameters #}
{% set num_init = 4 + 2 * (categorical + composition_constraint) if not dummy else 3 %}
{% set num_bayes = 15 if not dummy else 2 %}
{% set num_iter = num_init + num_bayes %}
{% if custom_gen -%}
gs = GenerationStrategy(
steps=[
GenerationStep(
model=Models.SOBOL,
num_trials={{ num_init }}, # how many sobol trials to perform (rule of thumb: 2 * number of params)
min_trials_observed=3,
max_parallelism=5,
{% if task == "Multi" %}
model_kwargs={"seed": 999, "transforms": Specified_Task_ST_MTGP_trans},
model_gen_kwargs={"deduplicate": True},
{% else %}
model_kwargs={"seed": 999},
{% endif %}
),
GenerationStep(
model=Models.{{ model_name }},
num_trials=-1,
max_parallelism=3,
model_kwargs={
{% if task == "Multi" %}
{% if model == "Fully Bayesian" %}
"num_samples": 512,
"warmup_steps": 512,
"transforms": Specified_Task_ST_MTGP_trans
{% elif model == "Custom" %}
"botorch_acqf_class": UpperConfidenceBound,
"transforms": Specified_Task_ST_MTGP_trans
{% else %}
"transforms": Specified_Task_ST_MTGP_trans
{% endif %}
{% elif model == "Fully Bayesian" %}
"num_samples": 512,
"warmup_steps": 512
{% elif model == "Custom" %}
"botorch_acqf_class": UpperConfidenceBound
{% else %}
{}
{% endif %}
},
),
]
)
{%- endif %}
ax_client = AxClient({% if custom_gen %}generation_strategy=gs{% endif %})
{% if composition_constraint -%}
{%- endif %}
ax_client.create_experiment(
parameters=[
{"name": "x1", "type": "range", "bounds": {% if composition_constraint %}[0.0, total]{% else %}[-5.0, 10.0]{% endif %}},
{"name": "x2", "type": "range", "bounds": {% if composition_constraint %}[0.0, total]{% else %}[0.0, 10.0]{% endif %}},
{% if task == "Multi"%}
{
"name": "task",
"type": "choice",
"values": ["A", "B"],
"is_task": True,
"target_value": "B"
}{% if categorical %},{% endif %}
{% endif %}
{% if categorical %}
{
"name": "c1",
"type": "choice",
"is_ordered": False,
"values": ["A", "B", "C"]
}
{% endif %}
],
objectives={
obj1_name: ObjectiveProperties(minimize=True{% if custom_threshold %}, threshold=25.0{% endif %}),
{% if objective == "Multi" -%}
obj2_name: ObjectiveProperties(minimize=True{% if custom_threshold %}, threshold=15.0{% endif %}),
{%- endif %}
},
{% if sum_constraint or composition_constraint or order_constraint or linear_constraint %}
parameter_constraints=[
{% if sum_constraint %}
{% if composition_constraint %}
"x1 + x2 <= 15.0", # example of a sum constraint, which may be redundant/unintended if composition_constraint is also selected
{% else %}
"x1 + x2 <= 15.0", # example of a sum constraint
{% endif %}
{% endif %}
{% if composition_constraint %}f"x1 + x2 <= {total}", # reparameterized compositional constraint, which is a type of sum constraint
{% endif %}
{% if order_constraint %}"x1 <= x2", # example of an order constraint
{% endif %}
{% if linear_constraint %}"1.0*x1 + 0.5*x2 <= 15.0", # example of a linear constraint. Note the lack of space around the asterisks
{% endif %}
],
{% endif %}
)
{% if existing_data -%}
# Add existing data to the AxClient
for i in range(n_train):
parameterization = X_train.iloc[i].to_dict()
{% if composition_constraint %}
# remove x3, since it's hidden from search space due to composition constraint
parameterization.pop('x3')
{% endif %}
ax_client.attach_trial(parameterization)
ax_client.complete_trial(trial_index=i, raw_data=y_train[i])
{%- endif %}
{# One BO step if dummy, TODO: change to 2+ if batch or asynchronous is selected #}
{% if synchrony == "Batch" %}
batch_size = 2
{% endif %}
{% set indent = " " if synchrony == "Batch" else "" %}
for i in range({{ num_iter }}):
{% if synchrony == "Single" and not task == "Multi" %}
parameterization, trial_index = ax_client.get_next_trial()
{% elif synchrony == "Single" and task == "Multi" %}
parameterization, trial_index = ax_client.get_next_trial(fixed_features=ObservationFeatures({"task": "A" if i % 2 == 0 else "B"}))
{% elif synchrony == "Batch" and task == "Multi" %}
parameterizations, optimization_complete = ax_client.get_next_trials(batch_size, fixed_features=ObservationFeatures({"task": "A" if i % 2 == 0 else "B"}))
for trial_index, parameterization in list(parameterizations.items()):
{% else %} {# if batch and task = singlee #}
parameterizations, optimization_complete = ax_client.get_next_trials(batch_size)
for trial_index, parameterization in list(parameterizations.items()):
{%- endif %}
# extract parameters {# Consider using **parameters instead, but might require explanation and a link to ** docs #}
{{ indent }}x1 = parameterization["x1"]
{{ indent }}x2 = parameterization["x2"]
{% if composition_constraint -%}
{{ indent }}x3 = total - (x1 + x2) # composition constraint: x1 + x2 + x3 == total
{%- endif %}
{% if task == "Multi" %}
{{ indent }}task = parameterization["task"]
{%- endif %}
{% if categorical -%}
{{ indent }}c1 = parameterization["c1"]
{%- endif %}
{{ indent }}results = {{ objective_function }}(
{{ indent }} x1, x2{% if composition_constraint %}, x3{% endif %}{% if categorical %}, c1{% endif %}{% if task == "Multi" %}, task{% endif %}
{{ indent }} )
{{ indent }}ax_client.complete_trial(trial_index=trial_index, raw_data=results)
{% if objective == "Multi" and task == "Single" -%}
pareto_results = ax_client.get_pareto_optimal_parameters()
{% elif objective == "Single" %}
best_parameters, metrics = ax_client.get_best_parameters()
{%- endif %}
{% if visualize %}
# Plot results
objectives = ax_client.objective_names
df = ax_client.get_trials_data_frame()
{%- if synchrony == "Batch" and objective == "Single"%}
df.index = df.index // batch_size
{%- endif %}
fig, ax = plt.subplots(figsize=(6, 4), dpi=150)
{%- if objective == "Single" %}
{%- if task == "Multi" %}
task = "A" # specify task results to plot
df = df[df.task == task]
ax.scatter(df.index, df[objectives], ec="k", fc="none", label="Observed")
ax.plot(df.index, np.minimum.accumulate(df[objectives]), color="#0033FF", lw=2, label="Best to Trial")
ax.set_title(f"Task {task}")
{%- else %}
ax.scatter(df.index, df[objectives], ec="k", fc="none", label="Observed")
ax.plot(df.index, np.minimum.accumulate(df[objectives]), color="#0033FF", lw=2, label="Best to Trial")
{%- endif %}
ax.set_xlabel("Trial Number")
ax.set_ylabel(objectives[0])
{%- elif task == "Multi" and objective == "Multi" %}
def get_pareto(df, task='A'):
t = df[df['task'] == task]
m = t.iloc[:,4:6].values # objectives are always cols 4,5
p = ~np.any(np.all(m[:,None] > m, axis=2), axis=1)
return [(dict(r[df.columns[6:-1]]), dict(r[df.columns[4:6]])) for i,r in t[p].iterrows()]
task = "A"
df = df[df.task == task]
pareto = get_pareto(df, task)
pareto_data = [p[1] for p in pareto]
pareto = pd.DataFrame(pareto_data).sort_values(objectives[0])
ax.scatter(df[objectives[0]], df[objectives[1]], fc="None", ec="k", label="Observed")
ax.plot(pareto[objectives[0]], pareto[objectives[1]], color="#0033FF", lw=2, label="Pareto Front")
ax.set_title(f"Task {task}")
ax.set_xlabel(objectives[0])
ax.set_ylabel(objectives[1])
{%- else %}
pareto = ax_client.get_pareto_optimal_parameters(use_model_predictions=False)
pareto_data = [p[1][0] for p in pareto.values()]
pareto = pd.DataFrame(pareto_data).sort_values(objectives[0])
ax.scatter(df[objectives[0]], df[objectives[1]], fc="None", ec="k", label="Observed")
ax.plot(pareto[objectives[0]], pareto[objectives[1]], color="#0033FF", lw=2, label="Pareto Front")
ax.set_xlabel(objectives[0])
ax.set_ylabel(objectives[1])
{%- endif %}
ax.legend()
plt.show()
{%- endif %}
Here are some other important files related to the Honegumi framework (applicable if you want to improve Honegumi or use it to create dynamic grid selections for other applications):
honegumi/ax/main.py.jinja which is the template thatβs supplied to the
Honegumiclass.honegumi/core/honegumi.html.jinja which updates docs/honegumi.html via scripts/generate_scripts.py
docs/honegumi.html also uses PyScript in conjunction with docs/main.py and docs/pyscript.toml to update the interactive grid on the website on-the-fly without pregenerating all possible combinations (this is the secret to the scalability of the Honegumi framework to many options).
Overall, Honegumi is designed to be a flexible workflow, ripe for integration with LLMs and agentic models to accelerate discovery in the experimental sciences.