This file provides guidance to AI coding agents when working with code in this repository.
# Install for development
pip install -e .[tests] # core + test tooling
pip install -e .[dev] # everything (tests, docs, examples, optional ML backends)
# Run tests
pytest tests/ # unit tests
pytest integration_tests/ # integration tests
pytest tests/.../test_file.py::test_name # single test (replace path and test name)
pytest --cov emukit --cov-report term-missing tests/ # with coverage
pytest -m 'not (gpy or pybnn or sklearn or notebooks)' # skip optional-dependency tests
pytest -m gpy # only GPy tests
# Lint and format (enforced in CI) — line length: 120 chars, flake8 exceptions: E731, E127
black .
isort .
flake8 .Emukit is a modular, framework-agnostic library for emulation-based decision-making (Bayesian optimization, experimental design, Bayesian quadrature, sensitivity analysis). The central design is the OuterLoop:
while stopping_condition not met:
candidate_point_calculator → next points to evaluate
user_function(points) → evaluations
model_updater → update model with new data
All loop components are swappable, enabling model-agnostic algorithms.
-
emukit/core/— All shared abstractions:interfaces/— Model interfaces (IModel,IDifferentiable,IJointlyDifferentiable,IPriorHyperparameters,IModelWithNoise)loop/—OuterLoop,LoopState,CandidatePointCalculator,ModelUpdater,StoppingCondition,UserFunction,EventHandleracquisition/—Acquisitionbase class; supports+,*,/operator overloading for composing acquisitionsoptimization/—AcquisitionOptimizer(maximizes acquisition over parameter space)parameter_space.py—ParameterSpacecomposed ofContinuousParameter,DiscreteParameter,CategoricalParameter,BanditParameterinitial_designs/— Sampling strategies for initializationencodings.py—OneHotEncoding,OrdinalEncoding
-
emukit/bayesian_optimization/—BayesianOptimizationLoop(wraps OuterLoop with sensible defaults), acquisitions (EI, EI-MCMC, entropy search, max-value entropy search, local penalization, NegativeLowerConfidenceBound, PoF, PoI) -
emukit/experimental_design/—ExperimentalDesignLoop, design-specific acquisitions -
emukit/quadrature/— Bayesian quadrature: specialized kernels, loop, andWarpedBayesianQuadratureModel -
emukit/multi_fidelity/— Multi-fidelity GP models built on GPy -
emukit/sensitivity/— Monte Carlo sensitivity analysis (Sobol indices) -
emukit/model_wrappers/— Bridges external ML libraries to emukit interfaces:GPyModelWrapper,GPyMultiOutputWrapper,SklearnModelWrapper,SimpleGaussianProcessModel -
emukit/samplers/— MCMC and other samplers -
emukit/test_functions/— Benchmark functions (Branin, Forrester, etc.)
Interface names are prefixed with I (e.g., IModel, IDifferentiable). Models only need to implement the interfaces required by the algorithms they are used with — there is no single monolithic model class. Type hints are required on all public functions.
Use Sphinx/reStructuredText (reST) style. Do not use Google style (Args:, Returns:) or NumPy style (section headers with underlines).
- Parameters:
:param name: description - Return value:
:return: description - Do not add
:type:or:rtype:tags — types belong in the function signature via type hints only - Document array shapes inline in the parameter description, e.g.
(n_points x n_dims) array
def sample_uniform(self, point_count: int) -> np.ndarray:
"""
Generates multiple uniformly distributed random parameter points.
:param point_count: number of data points to generate
:return: Generated points with shape (point_count, num_features)
"""Optional backends (GPy, pybnn/torch, sklearn) are guarded by pytest.importorskip() in tests and declared as optional extras in pyproject.toml. Tests for these backends are marked with @pytest.mark.gpy, @pytest.mark.pybnn, @pytest.mark.sklearn, or @pytest.mark.notebooks.
API docs are Sphinx-based and live in doc/. Each package has a hand-maintained .rst file in doc/api/ that lists its modules via .. automodule:: directives. Sphinx pulls docstrings from source automatically — but the .rst files must be kept in sync with the code structure.
Edit .rst files manually — do not use automated tools to regenerate them.
When to update doc/api/ .rst files:
- New file in an existing package: add a
.. automodule::block to the correspondingdoc/api/emukit.<package>.rst:.. automodule:: emukit.package.new_module :members: :undoc-members: :show-inheritance:
- New subpackage: create a new
doc/api/emukit.<newpackage>.rstand add it to thetoctreeof the parent.rst - Deleted or renamed module: remove or update the corresponding entry in the relevant
.rst
Verify the docs build locally whenever files under doc/ were changed or docstrings in source files were modified. Install dependencies first if needed (pip install -e .[dev]), then from inside the doc/ directory run:
make htmlNo need to run this if neither doc/ files nor any docstrings were touched.
Target branch: main on the upstream remote.
PR scope: One PR per functional change. Large changes must be split into multiple PRs with clear, independent scope — do not mix refactoring with new features or bundle unrelated fixes.
Pre-PR checklist:
- All unit tests pass (
pytest tests/) - Integration tests pass (
pytest integration_tests/) — run these unless the developer has indicated they will verify manually - Linting clean (
black .,isort .,flake8 .) - License headers present and up to date on all new files and files where logic or behaviour was changed (see below)
- If code structure changed (new, deleted, or renamed modules or subpackages):
doc/api/.rstfiles updated accordingly - If
doc/files or docstrings in source were changed:make htmlpasses (run fromdoc/) - PR description explicitly states that an AI agent was involved in the development
New files get only the Emukit Authors header (new files are not covered by the Amazon or Opsani copyrights):
# Copyright 2020-2026 The Emukit Authors. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0Replace the end year with the current year.
Existing files already have an Emukit Authors header, and may also have an Amazon or Opsani header below it. Only update the end year in the Emukit Authors line if it is behind the current year. Never modify the Amazon or Opsani headers.
Year update rule: Use 2020 as the fixed start year. Update the end year to the current year only for files where logic or behaviour was changed — not for whitespace, import reordering, or comment-only edits.