### Install and Use Pre-commit Hooks Source: https://experimental-design.github.io/bofire/CONTRIBUTING.md Install pre-commit and set up hooks for linting and formatting code locally. ```bash pip install pre-commit pre-commit install ``` -------------------------------- ### Manual Setup with Default Models Source: https://experimental-design.github.io/bofire/docs/tutorials/benchmarks/002-DTLZ2.html Manually sets up the DTLZ2 benchmark domain and MoboStrategy. This involves getting the domain, generating initial experiments, defining the strategy with a reference point, and then telling and asking for new candidates. ```python # we get the domain from the benchmark module, in real use case we have to build it on our own # make sure that the objective is set correctly domain = DTLZ2(dim=6).domain # we generate training data experiments = DTLZ2(dim=6).f(domain.inputs.sample(10), return_complete=True) # we setup the strategy # providing of a reference point is not mandatory but can help # the reference point has to be wrt to the assigned objective always worse than the points on the paretofront. data_model = MoboStrategy(domain=domain, ref_point={"f_0": 1.1, "f_1": 1.1}) recommender = strategies.map(data_model=data_model) # we tell the strategy our historical data recommender.tell(experiments=experiments) # we ask for a new point to evaluate candidates = recommender.ask(candidate_count=1) # we show the candidate display(candidates) # this candidate has to be then provided to the benchmark function and evaluated and then told back to the optimizer to get the next candidate ``` -------------------------------- ### Reaction Emulator Setup and Helper Functions Source: https://experimental-design.github.io/bofire/docs/tutorials/basic_examples/Reaction_Optimization_Example.html Imports necessary libraries and defines helper functions to simulate experimental data, including temperature factors, solvent density factors, and volume factors. This setup is crucial for emulating real experimental conditions. ```python # Reaction Optimization Notebook util code T0 = 25 T1 = 100 e0 = np.exp((T1 + 0) / T0) e60 = np.exp((T1 + 60) / T0) de = e60 - e0 boiling_points = { # in °C "MeOH": 64.7, "THF": 66.0, "Dioxane": 101.0, } density = { # in kg/l "MeOH": 0.792, "THF": 0.886, "Dioxane": 1.03, } # create dict from individual dicts descs = { "boiling_points": boiling_points, "density": density, } solvent_descriptors = pd.DataFrame(descs) # these functions are for faking real experimental data ;) def calc_volume_fact(V): # 20-90 # max at 75 = 1 # min at 20 = 0.7 # at 90=0.5 x = (V - 20) / 70 x = 0.5 + (x - 0.75) * 0.1 + (x - 0.4) ** 2 return x def calc_rhofact(solvent_type, Tfact): # between 0.7 and 1.1 x = solvent_descriptors["density"][solvent_type] x = (1.5 - x) * (Tfact + 0.5) / 2 return x.values def calc_Tfact(T): x = np.exp((T1 + T) / T0) return (x - e0) / de # this can be used to create a dataframe of experiments including yields def create_experiments(domain, nsamples=100, A=25, B=90, candidates=None): Tf = domain.inputs.get_by_key("Temperature") Vf = domain.inputs.get_by_key("Solvent Volume") typef = domain.inputs.get_by_key("Solvent Type") yf = domain.outputs.get_by_key("Yield") if candidates is None: T = np.random.uniform(low=Tf.lower_bound, high=Tf.upper_bound, size=(nsamples,)) V = np.random.uniform(low=Vf.lower_bound, high=Vf.upper_bound, size=(nsamples,)) solvent_types = [ domain.inputs.get_by_key("Solvent Type").categories[np.random.randint(0, 3)] for i in range(nsamples) ] else: nsamples = len(candidates) T = candidates["Temperature"].values V = candidates["Solvent Volume"].values solvent_types = candidates["Solvent Type"].values Tfact = calc_Tfact(T) rhofact = calc_rhofact(solvent_types, Tfact) Vfact = calc_volume_fact(V) y = A * Tfact + B * rhofact y = 0.5 * y + 0.5 * y * Vfact # y = y.values samples = pd.DataFrame( { Tf.key: T, Vf.key: V, yf.key: y, typef.key: solvent_types, "valid_" + yf.key: np.ones(nsamples), }, # index=pd.RangeIndex(nsamples), ) samples.index = pd.RangeIndex(nsamples) return samples def create_candidates(domain, nsamples=4): experiments = create_experiments(domain, nsamples=nsamples) candidates = experiments.drop(["Yield", "valid_Yield"], axis=1) return candidates # this is for evaluating candidates that do not yet have a yield attributed to it. def evaluate_experiments(domain, candidates): return create_experiments(domain, candidates=candidates) ``` -------------------------------- ### Set up synthetic example data Source: https://experimental-design.github.io/bofire/docs/tutorials/basic_examples/Outlier_Detection_and_Robust_GP.html Creates synthetic input and output features, samples initial experiments, and defines a prediction grid. This setup is for demonstrating outlier detection. ```python input_features = Inputs( features=[ContinuousInput(key=f"x_{i+1}", bounds=(-4, 4)) for i in range(1)], ) output_features = Outputs(features=[ContinuousOutput(key="y_1")]) experiments = input_features.sample(n=10) experiments["y_1"] = np.sin(experiments["x_1"]) experiments["valid_y_1"] = 1 experiments["valid_y_2"] = 1 # prediction grid x = pd.DataFrame(pd.Series(np.linspace(-4, 4, 100), name="x_1")) ``` -------------------------------- ### Setup for Single Objective Problem Source: https://experimental-design.github.io/bofire/docs/tutorials/serialization/strategies_serial.html Sets up a Himmelblau benchmark and generates initial training data and pending candidates for optimization. ```python benchmark = Himmelblau() samples = benchmark.domain.inputs.sample(n=10) # this is the training data experiments = benchmark.f(samples, return_complete=True) # this are the pending candidates pending_candidates = benchmark.domain.inputs.sample(2) ``` -------------------------------- ### Install BoFire with Optimization Features Source: https://experimental-design.github.io/bofire/install.html Installs BoFire including its core Bayesian optimization capabilities. Recommended for most users. ```bash pip install 'bofire[optimization]' ``` -------------------------------- ### Setup Formulation Wrapper for Himmelblau Benchmark Source: https://experimental-design.github.io/bofire/docs/tutorials/benchmarks/012-engineered_features.html Wraps the Himmelblau benchmark with FormulationWrapper to create a formulation problem with engineered features. This setup introduces new features derived from original ones and a filler feature to satisfy constraints. ```python bench = FormulationWrapper(benchmark=Himmelblau(), n_features_per_original_feature=3, n_filler_features=1) ``` -------------------------------- ### Setup an optimization strategy with Random Forest surrogates Source: https://experimental-design.github.io/bofire/docs/tutorials/advanced_examples/random_forest_in_bofire.html Initializes a multi-objective optimization strategy (MoboStrategy) using Random Forest surrogates for each objective. This setup is for a multi-objective problem where each output is modeled by a separate Random Forest. ```python benchmark = DTLZ2(dim=6) data_model = MoboStrategy( domain=benchmark.domain, ref_point={"f_0": 1.1, "f_1": 1.1}, surrogate_specs=BotorchSurrogates( surrogates=[ RandomForestSurrogate( inputs=benchmark.domain.inputs, outputs=Outputs(features=[benchmark.domain.outputs[0]]), ), RandomForestSurrogate( inputs=benchmark.domain.inputs, outputs=Outputs(features=[benchmark.domain.outputs[1]]), ), ], ), ) recommender = strategies.map(data_model=data_model) experiments = benchmark.f(benchmark.domain.inputs.sample(10), return_complete=True) recommender.tell(experiments=experiments) # currently not supported # for i in range(10): # samples = benchmark.domain.inputs.sample(512, method=SamplingMethodEnum.SOBOL) # candidates = recommender.ask(1, candidate_pool=samples) # candidates = candidates.reset_index(drop=True) # new_experiments = benchmark.f(candidates[benchmark.domain.inputs.get_keys().copy()], return_complete=True) # recommender.tell(experiments=new_experiments) ``` -------------------------------- ### Setup with Specific Models and Kernels Source: https://experimental-design.github.io/bofire/docs/tutorials/benchmarks/002-DTLZ2.html Sets up the MoboStrategy with specific surrogate models and kernels for different outputs. This allows for customized model configurations for each objective. ```python from bofire.data_models.kernels.api import RBFKernel, ScaleKernel from bofire.data_models.surrogates.api import BotorchSurrogates, SingleTaskGPSurrogate # in this case you would use non default kernels for the different outputs # it is also possible to build the models for a subset of the complete features data_model = MoboStrategy( domain=domain, ref_point={"f_0": 1.1, "f_1": 1.1}, surrogate_specs=BotorchSurrogates( surrogates=[ SingleTaskGPSurrogate( inputs=domain.inputs, outputs=Outputs(features=[domain.outputs[0]]), kernel=ScaleKernel(base_kernel=RBFKernel(ard=True)), ), SingleTaskGPSurrogate( inputs=domain.inputs, outputs=Outputs(features=[domain.outputs[1]]), kernel=ScaleKernel(base_kernel=RBFKernel(ard=False)), ), ], ), ) recommender = strategies.map(data_model=data_model) # we tell the strategy our historical data recommender.tell(experiments=experiments) # we ask for a new point to evaluate candidates = recommender.ask(candidate_count=1) # we show the candidate display(candidates) ``` -------------------------------- ### Multi-Fidelity Strategy Setup Source: https://experimental-design.github.io/bofire/docs/tutorials/advanced_examples/multifidelity_bo.html Configure a MultiFidelityStrategy for Bayesian Optimization. This setup is useful when dealing with optimization problems where different fidelity levels of experiments are available. ```python mf_data_model = MultiFidelityStrategy( domain=mf_benchmark.domain, acquisition_function=qLogEI(), fidelity_thresholds=0.1, ) mf_data_model.surrogate_specs.surrogates[0].inputs ``` -------------------------------- ### Setup MOBO Strategy Domain Source: https://experimental-design.github.io/bofire/docs/tutorials/serialization/strategies_serial.html Generates samples and experiments for a multiobjective domain using the DTLZ2 benchmark. This is a prerequisite for setting up the MOBO strategy. ```python benchmark = DTLZ2(dim=6) samples = benchmark.domain.inputs.sample(n=20) experiments = benchmark.f(samples, return_complete=True) pending_candidates = benchmark.domain.inputs.sample(2) ``` -------------------------------- ### ShortestPathStrategy.step Source: https://experimental-design.github.io/bofire/docs/reference/strategies.api.html Takes a starting point and returns the next step in the shortest path. ```APIDOC ## ShortestPathStrategy.step ### Description Takes a starting point and returns the next step in the shortest path. ### Method Signature ```python strategies.api.ShortestPathStrategy.step() ``` ``` -------------------------------- ### ShortestPathStrategy.step Source: https://experimental-design.github.io/bofire/docs/reference/strategies.api.html Takes a starting point and returns the next step in the shortest path. ```APIDOC ## ShortestPathStrategy.step ### Description Takes a starting point and returns the next step in the shortest path. ### Method None (This is a method of the ShortestPathStrategy class) ### Endpoint None ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example None ### Response #### Success Response (200) None #### Response Example None ### Parameters * **start** (pd.Series): The starting point for the shortest path. ### Returns * **pd.Series**: The next step in the shortest path. ``` -------------------------------- ### Setup and Visualize Full Factorial Design Source: https://experimental-design.github.io/bofire/docs/tutorials/doe/fractional_factorial.html Configures a full factorial design with center points and repetitions, generates the design, and plots it. ```python #| papermill: {duration: 0.193231, end_time: '2024-10-10T20:36:14.897979', exception: false, start_time: '2024-10-10T20:36:14.704748', status: completed} #| tags: [] strategy_data = FractionalFactorialStrategy( domain=domain, n_center=1, # number of center points n_repetitions=1, # number of repetitions, we do only one round here ) strategy = strategies.map(strategy_data) design = strategy.ask() display(design) plot_design(design=design) ``` -------------------------------- ### Problem Setup and Data Sampling Source: https://experimental-design.github.io/bofire/docs/tutorials/basic_examples/Model_Fitting_and_analysis.html Defines input and output features, samples data from a Himmelblau benchmark function, and adds experimental metadata. ```python #| papermill: {duration: 0.010285, end_time: '2024-10-10T20:34:24.696815', exception: false, start_time: '2024-10-10T20:34:24.686530', status: completed} #| tags: [] input_features = Inputs( features=[ContinuousInput(key=f"x_{i+1}", bounds=(-4, 4)) for i in range(3)], ) output_features = Outputs(features=[ContinuousOutput(key="y")]) experiments = input_features.sample(n=50) experiments.eval("y=((x_1**2 + x_2 - 11)**2+(x_1 + x_2**2 -7)**2)", inplace=True, engine = "python") experiments["valid_y"] = 1 experiments["labcode"] = "exp_" + experiments.index.astype(str) ``` -------------------------------- ### Setup MoboStrategy with specific surrogate models Source: https://experimental-design.github.io/bofire/docs/tutorials/benchmarks/002-DTLZ2.html Illustrates how to configure MoboStrategy with custom surrogate models, such as specifying non-default kernels for different output features. ```python from bofire.data_models.kernels.api import RBFKernel, ScaleKernel from bofire.data_models.surrogates.api import BotorchSurrogates, SingleTaskGPSurrogate # in this case you would use non default kernels for the different outputs ``` -------------------------------- ### Install Minimal BoFire using pip Source: https://experimental-design.github.io/bofire/install.html Installs the basic BoFire package with only data models. Use this for a lightweight setup. ```bash pip install bofire ``` -------------------------------- ### Get Next Step in ShortestPathStrategy Source: https://experimental-design.github.io/bofire/docs/reference/strategies.api.html Calculates and returns the next step in the shortest path from a given starting point. The input 'start' should be a pandas Series. ```python strategies.api.ShortestPathStrategy.step(start) ``` -------------------------------- ### Initialize Reaction Emulation Utilities Source: https://experimental-design.github.io/bofire/docs/tutorials/basic_examples/Reaction_Optimization_Example.html Set up constants and dictionaries for emulating reaction experiments, including physical properties like boiling points and densities. ```python # Reaction Optimization Notebook util code T0 = 25 T1 = 100 e0 = np.exp((T1 + 0) / T0) e60 = np.exp((T1 + 60) / T0) de = e60 - e0 boiling_points = { # in °C "MeOH": 64.7, "THF": 66.0, "Dioxane": 101.0, } density = { # in kg/l "MeOH": 0.792, "THF": 0.886, "Dioxane": 1.03, } # create dict from individual dicts descs = { "boiling_points": boiling_points, "density": density, } solvent_descriptors = pd.DataFrame(descs) # these functions are for faking real experimental data ;) def calc_volume_fact(V): # 20-90 # max at 75 = 1 # min at 20 = 0.7 # at 90=0.5 x = (V - 20) / 70 x = 0.5 + (x - 0.75) * 0.1 + (x - 0.4) ** 2 return x def calc_rhofact(solvent_type, Tfact): # between 0.7 and 1.1 x = solvent_descriptors["density"][solvent_type] x = (1.5 - x) * (Tfact + 0.5) / 2 return x.values def calc_Tfact(T): x = np.exp((T1 + T) / T0) return (x - e0) / de ``` -------------------------------- ### Setup SVM benchmark and initial experiments Source: https://experimental-design.github.io/bofire/docs/tutorials/benchmarks/013-spherical_kernel.html Initializes the SVM benchmark, samples initial candidates, and prepares the first set of experiments including objective function values. ```python # problem setup for spherical linear kernels benchmark = SVM() candidates = benchmark._domain.inputs.sample(benchmark.dim+1, seed=benchmark.seed) experiments = candidates.copy() result = benchmark._f(experiments) # Add empty columns 'y' and 'valid_y' to experiments DataFrame experiments["y"], experiments["valid_y"] = result["y"], result["valid_y"] ``` -------------------------------- ### Batch Constraints for Parallel Experiments Source: https://experimental-design.github.io/bofire/docs/tutorials/doe/basic_examples.html Creates designs where `multiplicity` subsequent experiments share the same value for a feature, useful for parallel setups. This example fixes 'x1' for batches of 3 experiments. ```python domain = Domain( inputs=[ ContinuousInput(key="x1", bounds=(0, 1)), ContinuousInput(key="x2", bounds=(0, 1)), ContinuousInput(key="x3", bounds=(0, 1)), ], outputs=[ContinuousOutput(key="y")], constraints=[InterpointEqualityConstraint(features=["x1"], multiplicity=3)], ) data_model = DoEStrategy( domain=domain, criterion=DOptimalityCriterion(formula="linear"), ipopt_options={"max_iter": 500, "print_level": 0}, ) strategy = strategies.map(data_model=data_model) result = strategy.ask(12) result.round(3) ``` -------------------------------- ### Build Documentation Locally Source: https://experimental-design.github.io/bofire/CONTRIBUTING.md Build the project documentation locally using Quarto and Quartodoc. ```bash quartodoc build quarto render ``` -------------------------------- ### Import necessary libraries for BoFire active learning Source: https://experimental-design.github.io/bofire/docs/tutorials/benchmarks/011-ActiveLearning.html Imports essential libraries for BoFire, including strategies, benchmarks, data models, and runners. This setup is required for active learning examples. ```python import os import matplotlib.pyplot as plt import numpy as np import pandas as pd from matplotlib import cm import bofire.strategies.api as strategies from bofire.benchmarks.api import GenericBenchmark from bofire.benchmarks.single import Himmelblau from bofire.data_models.api import Domain, Inputs, Outputs from bofire.data_models.features.api import ContinuousInput, ContinuousOutput from bofire.data_models.objectives.api import MinimizeObjective from bofire.data_models.strategies.api import RandomStrategy from bofire.runners.api import run SMOKE_TEST = os.environ.get("SMOKE_TEST") ``` -------------------------------- ### Import necessary libraries for BoFire Source: https://experimental-design.github.io/bofire/docs/tutorials/advanced_examples/transfer_learning_bo.html Imports essential libraries and modules from BoFire for Bayesian optimization, including strategies, surrogates, data models, and benchmarks. This setup is required for most BoFire examples. ```python import os import numpy as np import pandas as pd from tqdm import tqdm import bofire.strategies.api as strategies import bofire.surrogates.api as surrogates from bofire.benchmarks.api import Ackley, Branin from bofire.data_models.acquisition_functions.api import qLogEI from bofire.data_models.domain.api import Domain, Inputs, Outputs from bofire.data_models.features.api import ContinuousInput, ContinuousOutput, TaskInput from bofire.data_models.objectives.api import MaximizeObjective from bofire.data_models.strategies.api import SoboStrategy from bofire.data_models.surrogates.api import ( BotorchSurrogates, MultiTaskGPSurrogate, SingleTaskGPSurrogate, ) ``` -------------------------------- ### Setup SingleTaskGPSurrogate Data Model Source: https://experimental-design.github.io/bofire/docs/tutorials/serialization/models_serial.html Initializes a SingleTaskGPSurrogate data model with specified input and output features. This is the first step before generating its JSON spec. ```python # we setup the data model, here a Single Task GP surrogate_data = SingleTaskGPSurrogate(inputs=input_features, outputs=output_features) ``` -------------------------------- ### Install BoFire with All Dependencies Source: https://experimental-design.github.io/bofire/CONTRIBUTING.md Install BoFire in editable mode with all optional dependencies for development. ```bash pip install -e ".[all]" ``` -------------------------------- ### Setup and Serialize MOBO Strategy Source: https://experimental-design.github.io/bofire/docs/tutorials/serialization/strategies_serial.html Set up the MOBO strategy data model, defining the domain and surrogate specifications. Generate the JSON specification for this multiobjective strategy. ```python # setup the data model strategy_data = MoboStrategyDataModel( domain=benchmark.domain, surrogate_specs=BotorchSurrogates( surrogates=[ SingleTaskGPSurrogate( inputs=benchmark.domain.inputs, outputs=Outputs(features=[benchmark.domain.outputs[0]]), kernel=ScaleKernel(base_kernel=RBFKernel(ard=False)), ), ], ), ) # we generate the json spec jspec = strategy_data.model_dump_json() ``` -------------------------------- ### Initialize Surrogate Models for Multi-Objective Optimization Source: https://experimental-design.github.io/bofire/docs/userguides/surrogates.html This example demonstrates initializing different surrogate models for multiple objectives within a multi-objective optimization strategy. It shows how to specify surrogate models for each objective using `SingleTaskGPSurrogate` and `RandomForestSurrogate` and then integrate them into a `QparegoStrategy`. ```python surrogate_data_0 = SingleTaskGPSurrogate( inputs=domain.inputs, outputs=Outputs(features=[domain.outputs[0]]), ) surrogate_data_1 = RandomForestSurrogate( inputs=domain.inputs, outputs=Outputs(features=[domain.outputs[1]]), ) qparego_data_model = QparegoStrategy( domain=domain, surrogate_specs=BotorchSurrogates( surrogates=[surrogate_data_0, surrogate_data_1] ), ) ``` -------------------------------- ### Instantiate SingleTaskGPSurrogate with Noise Model Source: https://experimental-design.github.io/bofire/docs/userguides/surrogates.html This example shows how to configure a `SingleTaskGPSurrogate` with a specified kernel and a `NormalPrior` for noise. Use `NormalPrior` when the noise is expected to be Gaussian. ```python surrogate_data_0 = SingleTaskGPSurrogate( inputs=domain.inputs, outputs=Outputs(features=[domain.outputs[0]]), kernel=PolynomialKernel(power=2), noise_prior=NormalPrior(loc=0, scale=1) ) ``` -------------------------------- ### Manual Setup of ActiveLearning Strategy Source: https://experimental-design.github.io/bofire/docs/tutorials/benchmarks/011-ActiveLearning.html Initializes and configures the ActiveLearningStrategy with a specified acquisition function and domain. It then tells the strategy about initial experiments and asks for the first set of candidates. ```python from bofire.data_models.acquisition_functions.api import qNegIntPosVar from bofire.data_models.strategies.api import ActiveLearningStrategy from bofire.data_models.surrogates.api import BotorchSurrogates, SingleTaskGPSurrogate af = qNegIntPosVar( n_mc_samples=64, # lower the number of monte carlo samples to improve speed ) data_model = ActiveLearningStrategy(domain=himmelblau.domain, acquisition_function=af) recommender = strategies.map(data_model=data_model) recommender.tell(experiments=initial_experiments) candidates = recommender.ask(candidate_count=1) ``` -------------------------------- ### Install BoFire with Additional Dependencies Source: https://experimental-design.github.io/bofire/install.html Installs BoFire with specified optional dependencies like 'optimization' and 'cheminfo'. Customize as needed. ```bash pip install 'bofire[optimization, cheminfo] # will install bofire with additional dependencies `optimization` and `cheminfo` ``` -------------------------------- ### Development Installation of BoFire Source: https://experimental-design.github.io/bofire/install.html Installs the BoFire repository in editable mode, including optional dependencies like 'optimization' and 'tests'. Recommended for contributors. ```bash pip install -e ".[optimization, tests]" # include optional dependencies as you wish ``` -------------------------------- ### Setup SoboStrategy for Candidate Generation Source: https://experimental-design.github.io/bofire/docs/tutorials/basic_examples/Unknown_Constraint_Classification.html Configure a SoboStrategy with a domain, acquisition function (qLogEI), and surrogate specifications. This strategy is used for generating candidates, modeling categorical outputs as constraints in the acquisition function optimization. ```python from bofire.data_models.acquisition_functions.api import qLogEI from bofire.data_models.strategies.api import SoboStrategy from bofire.data_models.surrogates.api import BotorchSurrogates strategy_data = SoboStrategy( domain=domain1, acquisition_function=qLogEI(), surrogate_specs=BotorchSurrogates( surrogates=[surrogate_data], ), ) strategy = strategies.map(strategy_data) strategy.tell(sample_df) ``` -------------------------------- ### Setup and Use MultiplicativeSoboStrategy with Custom Surrogates Source: https://experimental-design.github.io/bofire/docs/tutorials/advanced_examples/objectives_on_inputs.html Sets up a SoboStrategy using custom surrogates for specified outputs and requests new candidate points. The surrogate for 'y' defaults to SingleTaskGPSurrogate. ```python strategy_data = MultiplicativeSoboStrategy( domain=domain, surrogate_specs=BotorchSurrogates( surrogates=[surrogate_data, categorical_surrogate_data] ), ) strategy = strategies.map(strategy_data) strategy.tell(experiments) strategy.ask(4) ``` -------------------------------- ### Install cyipopt using Conda Source: https://experimental-design.github.io/bofire/install.html Installs the cyipopt package and its dependencies via conda, required for BoFire's model-based DoE functionalities. ```bash conda install -c conda-forge cyipopt ``` -------------------------------- ### Configure Multiple Surrogate Models for Qparego Strategy Source: https://experimental-design.github.io/bofire/docs/userguides/surrogates.html This example demonstrates how to initialize and configure multiple surrogate models (SingleTaskGPSurrogate and RandomForestSurrogate) and then use them within the QparegoStrategy for multi-objective optimization. ```python surrogate_data_0 = SingleTaskGPSurrogate( inputs=domain.inputs, outputs=Outputs(features=[domain.outputs[0]]), ) surrogate_data_1 = RandomForestSurrogate( inputs=domain.inputs, outputs=Outputs(features=[domain.outputs[1]]), ) qparego_data_model = QparegoStrategy( domain=domain, surrogate_specs=BotorchSurrogates( surrogates=[surrogate_data_0, surrogate_data_1] ), ) ``` -------------------------------- ### Get Feature Keys by Type Source: https://experimental-design.github.io/bofire/docs/tutorials/basic_examples/basic_terminology.html Retrieve a list of keys for features that match a specified type using the `get_keys` method. This method follows the same logic as the `get` method. ```python input_features.get_keys(CategoricalInput) ``` -------------------------------- ### Manual Setup of ActiveLearningStrategy Source: https://experimental-design.github.io/bofire/docs/tutorials/benchmarks/011-ActiveLearning.html Manually configure the `ActiveLearningStrategy` with a specific acquisition function (`qNegIntPosVar`) and domain. The `n_mc_samples` parameter in the acquisition function can be adjusted to balance speed and accuracy. ```python # | output: false # Manual set up of ActiveLearning from bofire.data_models.acquisition_functions.api import qNegIntPosVar from bofire.data_models.strategies.api import ActiveLearningStrategy from bofire.data_models.surrogates.api import BotorchSurrogates, SingleTaskGPSurrogate af = qNegIntPosVar( n_mc_samples=64, # lower the number of monte carlo samples to improve speed ) data_model = ActiveLearningStrategy(domain=himmelblau.domain, acquisition_function=af) ecommender = strategies.map(data_model=data_model) ecommender.tell(experiments=initial_experiments) candidates = recommender.ask(candidate_count=1) ``` -------------------------------- ### Manual Domain Setup Source: https://experimental-design.github.io/bofire/docs/tutorials/benchmarks/009-BNH.html Defines the input and output features for the domain, including continuous inputs and outputs with minimization and sigmoid objectives for constraints. Use this to configure the optimization problem. ```python domain = Domain( inputs=Inputs( features=[ ContinuousInput(key="x1", bounds=(0, 5)), ContinuousInput(key="x2", bounds=(0, 3)), ], ), outputs=Outputs( features=[ ContinuousOutput(key="f1", objective=MinimizeObjective()), ContinuousOutput(key="f2", objective=MinimizeObjective()), # these are the output constraints, choose MinimizeSigmoidObjective for lower bound constraints # and MaximizeSigmoidObjective for upper bound constraints # tp is the threshold point, steepness is the steepness of the sigmoid that is applied to the constraint # usually a steepness of 1000 is fine. ContinuousOutput( key="c1", objective=MinimizeSigmoidObjective(tp=25, steepness=1000), ), ContinuousOutput( key="c2", objective=MaximizeSigmoidObjective(tp=7.7, steepness=1000), ), ], ), ) ``` -------------------------------- ### Install LLM extra and set API key Source: https://experimental-design.github.io/bofire/docs/tutorials/advanced_examples/llm_molecular.html Install the optional 'llm' extra for BoFire and ensure your Anthropic API key is set in the environment. This is required for LLM interactions. ```bash pip install "bofire[llm]" ``` -------------------------------- ### Setup and Serialize SOBO Strategy Source: https://experimental-design.github.io/bofire/docs/tutorials/serialization/strategies_serial.html Set up the SOBO strategy data model, including domain and acquisition function, then generate its JSON specification. This spec can be used to recreate the strategy later. ```python # setup the data model strategy_data = SoboStrategyDataModel( domain=benchmark.domain, acquisition_function=qLogNEI(), ) # we generate the json spec jspec = strategy_data.model_dump_json() ``` -------------------------------- ### Setup for Spherical Linear Kernel Optimization Source: https://experimental-design.github.io/bofire/docs/tutorials/benchmarks/013-spherical_kernel.html Imports necessary modules and sets up the SVM benchmark problem. It samples initial candidates and evaluates them to create the first set of experiments. ```python from bofire.benchmarks.svm import SVM from bofire.data_models.strategies.api import SoboStrategy from bofire.data_models.kernels.api import SphericalLinearKernel from bofire.data_models.surrogates.api import SingleTaskGPSurrogate, BotorchSurrogates import bofire.strategies.api as strategies ``` ```python # problem setup for spherical linear kernels benchmark = SVM() candidates = benchmark._domain.inputs.sample(benchmark.dim+1, seed=benchmark.seed) experiments = candidates.copy() result = benchmark._f(experiments) # Add empty columns 'y' and 'valid_y' to experiments DataFrame experiments["y"], experiments["valid_y"] = result["y"], result["valid_y"] ``` ```python sobo_strategy_data_model = SoboStrategy( domain=benchmark._domain, seed=benchmark.seed, surrogate_specs=BotorchSurrogates( surrogates=[ SingleTaskGPSurrogate( inputs=benchmark._domain.inputs, outputs=benchmark._domain.outputs, kernel=SphericalLinearKernel(), ) ] ), ) strategy = strategies.map(sobo_strategy_data_model) ``` -------------------------------- ### ShortestPathStrategy.step Source: https://experimental-design.github.io/bofire/docs/reference/strategies.api.html Calculates the next step in the shortest path from a given starting point. ```APIDOC ## ShortestPathStrategy.step ### Description Takes a starting point and returns the next step in the shortest path. ### Method `strategies.api.ShortestPathStrategy.step(start)` ### Parameters #### Path Parameters - **start** (pd.Series) - Required - The starting point for the shortest path. ### Returns #### Success Response - **pd.Series** - The next step in the shortest path. ``` -------------------------------- ### Setup Random Strategy for Initial Sampling Source: https://experimental-design.github.io/bofire/docs/tutorials/basic_examples/Reaction_Optimization_Example.html Sets up a Random Strategy for generating initial experiments. This is useful when a BO strategy needs a certain amount of data to build its initial regression model. ```python # a random strategy from bofire.data_models.strategies.api import RandomStrategy as RandomStrategyModel random_strategy_model = RandomStrategyModel(domain=domain) # we have to provide the strategy with our optimization problem so it knows where to sample from. random_strategy = strategies.map(random_strategy_model) ``` -------------------------------- ### Setup Random Forest and Generate Data Source: https://experimental-design.github.io/bofire/docs/tutorials/advanced_examples/random_forest_in_bofire.html Initializes a benchmark problem and generates experimental data. This data is used to train the Random Forest surrogate model. ```python benchmark = DTLZ2(dim=6) experiments = benchmark.f(benchmark.domain.inputs.sample(20), return_complete=True) ``` -------------------------------- ### Basic BoFire Functionality Overview Source: https://experimental-design.github.io/bofire/docs/tutorials/basic_examples This markdown section outlines the core capabilities demonstrated in the basic examples, such as setting up reaction domains, defining objectives, and running optimization loops. It serves as an introduction to the available tutorials. ```markdown --- title: "Basic Examples" --- # Basic Examples These notebooks demonstrate the basic functionality of BoFire, including: - Setting up reaction domains - Defining objectives - Running Bayesian optimization loops - Model fitting and analysis - Outlier detection and robust Gaussian Processes - Unknown constraint classification ## Available Tutorials ### [Basic Terminology](basic_terminology.qmd) Introduction to fundamental concepts and terminology used throughout BoFire. ### [Reaction Optimization Example](Reaction_Optimization_Example.qmd) A comprehensive example showing how to optimize chemical reactions using BoFire. ### [Model Fitting and Analysis](Model_Fitting_and_analysis.qmd) Learn how to fit surrogate models and analyze their performance. ### [Outlier Detection and Robust GP](Outlier_Detection_and_Robust_GP.qmd) Techniques for detecting outliers and building robust Gaussian Process models. ### [Unknown Constraint Classification](Unknown_Constraint_Classification.qmd) Handling and classifying unknown constraints in optimization problems. ### [Index Kernel and Positive Index Kernel](index_kernel.qmd) Learn how to use Index Kernel and Positive Index Kernel for categorical variables. ``` -------------------------------- ### validate_smiles Source: https://experimental-design.github.io/bofire/docs/reference/data_models.features.api.html Validates if a list of strings are valid SMILES. This check requires RDKit to be installed. ```APIDOC ## validate_smiles ### Description Validates that categories are valid smiles. Note that this check can only be executed when rdkit is available. ### Method `CategoricalMolecularInput.validate_smiles(categories)` ### Parameters #### Path Parameters - None #### Query Parameters - None #### Request Body - **categories** (List[str]) - Required - List of smiles. ### Request Example ```python # Example usage # categorical_molecular_input_instance.validate_smiles(['CCO', 'C1=CC=CC=C1']) ``` ### Response #### Success Response (200) - **List of smiles** (List[str]) - A list of the validated SMILES strings. #### Response Example ```json { "example": "List[str]: List of the smiles" } ``` ### Error Handling - **ValueError**: Raised when a string in the list is not a valid SMILES format. ``` -------------------------------- ### CategoricalInput Get Forbidden Categories Source: https://experimental-design.github.io/bofire/docs/reference/data_models.features.api.html Retrieves the list of non-allowed categories for a CategoricalInput feature. ```python data_models.features.api.CategoricalInput.get_forbidden_categories() ``` -------------------------------- ### CategoricalInput Get Allowed Categories Source: https://experimental-design.github.io/bofire/docs/reference/data_models.features.api.html Retrieves the list of allowed categories for a CategoricalInput feature. ```python data_models.features.api.CategoricalInput.get_allowed_categories() ``` -------------------------------- ### Setup and Custom Objective Function Source: https://experimental-design.github.io/bofire/docs/tutorials/advanced_examples/custom_sobo.html Set up the optimization benchmark, initialize the CustomSoboStrategy, and define a custom objective function that manipulates the inferred quantity by subtracting an input feature. ```python benchmark = Himmelblau() experiments = benchmark.f(benchmark.domain.inputs.sample(10), return_complete=True) strategy_data = CustomSoboStrategy(domain=benchmark.domain) strategy = strategies.map(strategy_data) # here we find out what is the index of the input feature in the input tensor `X` # in the manipulation function below feature2index, _ = strategy.domain.inputs._get_transform_info( strategy.input_preprocessing_specs ) feat_idx = feature2index["x_1"][0] # we assign now a torch based function to the strategy which performs the custom manipulation of the objective # the signature has to be understood in the following way: # - samples: the samples to evaluate the objective on, these are the predicted Y/output values of the model(s) # - callables: the botorch callables associated to objectives associated to the features # (have a look at `get_objective_callable` in `bofire/utils/torch_tools.py`) # - weights: the weights associated to the objectives # (have a look here: `_callables_and_weights` in `bofire/utils/torch_tools.py`) # - X: a tensor of input values associated to the output values samples, associated to the Y/output values (`samples`) def f(samples, callables, weights, X): val = torch.tensor(0.0).to(**tkwargs) for c, w in zip(callables, weights): val = val + c(samples, None) * w # here, you have to implement the custom manipulation of the objective # in this example, we subtract the value of the first feature from the objective val = val - X[..., feat_idx] return val strategy.f = f strategy.tell(experiments) strategy.ask(1) ``` -------------------------------- ### get_free Source: https://experimental-design.github.io/bofire/docs/reference/data_models.domain.features.Inputs.html Gets all features in the Inputs object that are not fixed and returns them as a new Inputs object. ```APIDOC ## get_free ### Description Gets all features in `self` that are not fixed and returns them as. ### Method GET ### Endpoint /inputs/free ### Response #### Success Response (200) - **free_inputs** (Inputs) - A new Inputs object containing only the free features. ``` -------------------------------- ### Initialize Himmelblau benchmark and sample initial data Source: https://experimental-design.github.io/bofire/docs/tutorials/benchmarks/011-ActiveLearning.html Sets up the Himmelblau benchmark and generates initial data points using a RandomStrategy. This data is crucial for initializing the Gaussian Regression Model used by the active learning strategy. ```python himmelblau = Himmelblau() def sample(domain: Domain): datamodel = RandomStrategy(domain=domain) sampler = strategies.map(data_model=datamodel) sampled = sampler.ask(10) return sampled initial_points = sample(domain=himmelblau.domain) initial_experiments = pd.concat([initial_points, himmelblau.f(initial_points)], axis=1) display(initial_experiments) ``` -------------------------------- ### Get Torch Executable Objectives Source: https://experimental-design.github.io/bofire/docs/tutorials/advanced_examples/merging_objectives.html Retrieves the objective functions as PyTorch executables for evaluation. ```python # get the objectives for evaluation as a torch executable objectives = { key: strategy._get_objective_and_constraints()[0] for (key, strategy) in strategy.items() } ``` -------------------------------- ### get_free Source: https://experimental-design.github.io/bofire/docs/reference/data_models.domain.features.Inputs.html Gets all features in the current Inputs object that are not fixed and returns them as a new Inputs object. ```APIDOC ## get_free ### Description Gets all features in `self` that are not fixed and returns them as new `Inputs` object. ### Method `data_models.domain.features.Inputs.get_free()` ### Returns #### Success Response - **Inputs** - Input features object containing only non-fixed features. ``` -------------------------------- ### Setup and Model Fitting with BoFire Source: https://experimental-design.github.io/bofire/docs/tutorials/serialization/models_serial.html Sets up a Himmelblau benchmark and fits a SingleTaskGP model to sampled data. Demonstrates the creation of input and output feature specifications. ```python from pydantic import TypeAdapter import bofire.surrogates.api as surrogates from bofire.benchmarks.multi import CrossCoupling from bofire.benchmarks.single import Himmelblau from bofire.data_models.domain.api import Outputs from bofire.data_models.enum import CategoricalEncodingEnum from bofire.data_models.surrogates.api import ( AnySurrogate, EmpiricalSurrogate, MixedSingleTaskGPSurrogate, RandomForestSurrogate, RegressionMLPEnsemble, SingleTaskGPSurrogate, ) benchmark = Himmelblau() samples = benchmark.domain.inputs.sample(n=50) experiments = benchmark.f(samples, return_complete=True) experiments.head(10) ``` ```python input_features = benchmark.domain.inputs output_features = benchmark.domain.outputs ``` ```python input_features.model_dump_json() ``` ```json {"type":"Inputs","features":[{"type":"ContinuousInput","key":"x_1","context":null,"unit":null,"bounds":[-6.0,6.0],"local_relative_bounds":null,"stepsize":null,"allow_zero":false},{"type":"ContinuousInput","key":"x_2","context":null,"unit":null,"bounds":[-6.0,6.0],"local_relative_bounds":null,"stepsize":null,"allow_zero":false}]} ``` ```python output_features.model_dump_json() ``` ```json {"type":"Outputs","features":[{"type":"ContinuousOutput","key":"y","context":null,"unit":null,"objective":{"type":"MinimizeObjective","w":1.0,"bounds":[0.0,1.0]}}]} ``` ```python # we setup the data model, here a Single Task GP surrogate_data = SingleTaskGPSurrogate(inputs=input_features, outputs=output_features) ``` -------------------------------- ### get_fixed Source: https://experimental-design.github.io/bofire/docs/reference/data_models.domain.features.Inputs.html Gets all features in the current Inputs object that are fixed and returns them as a new Inputs object. ```APIDOC ## get_fixed ### Description Gets all features in `self` that are fixed and returns them as new `Inputs` object. ### Method `data_models.domain.features.Inputs.get_fixed()` ### Returns #### Success Response - **Inputs** - Input features object containing only fixed features. ``` -------------------------------- ### Setup and run custom optimization Source: https://experimental-design.github.io/bofire/docs/tutorials/advanced_examples/custom_sobo.html Sets up the Himmelblau benchmark, initializes the `CustomSoboStrategy`, defines a custom objective function `f` that subtracts the value of feature 'x_1' from the combined objectives, and then tells the strategy about experiments and asks for the next best point. ```python benchmark = Himmelblau() experiments = benchmark.f(benchmark.domain.inputs.sample(10), return_complete=True) strategy_data = CustomSoboStrategy(domain=benchmark.domain) strategy = strategies.map(strategy_data) # here we find out what is the index of the input feature in the input tensor `X` # in the manipulation function below feature2index, _ = strategy.domain.inputs._get_transform_info( strategy.input_preprocessing_specs ) feat_idx = feature2index["x_1"][0] # we assign now a torch based function to the strategy which performs the custom manipulation of the objective # the signature has to be understood in the following way: # - samples: the samples to evaluate the objective on, these are the predicted Y/output values of the model(s) # - callables: the botorch callables associated to objectives associated to the features # (have a look at `get_objective_callable` in `bofire/utils/torch_tools.py`) # - weights: the weights associated to the objectives # (have a look here: `_callables_and_weights` in `bofire/utils/torch_tools.py`) # - X: a tensor of input values associated to the output values samples, associated to the Y/output values (`samples`) def f(samples, callables, weights, X): val = torch.tensor(0.0).to(**tkwargs) for c, w in zip(callables, weights): val = val + c(samples, None) * w # here, you have to implement the custom manipulation of the objective # in this example, we subtract the value of the first feature from the objective val = val - X[..., feat_idx] return val strategy.f = f strategy.tell(experiments) strategy.ask(1) ``` -------------------------------- ### get_number_of_categorical_combinations Source: https://experimental-design.github.io/bofire/docs/reference/data_models.domain.features.Inputs.html Get the total number of unique categorical combinations possible based on the defined features. ```APIDOC ## get_number_of_categorical_combinations ### Description Get the total number of unique categorical combinations. ### Method GET ### Endpoint /inputs/number_of_categorical_combinations ### Response #### Success Response (200) - **count** (int) - The total number of unique categorical combinations. ``` -------------------------------- ### Initialize QparegoStrategy Source: https://experimental-design.github.io/bofire/docs/reference/strategies.api.html Initializes the QparegoStrategy. This strategy is used for multi-objective optimization problems. ```python strategies.api.QparegoStrategy(data_model, **kwargs) ``` -------------------------------- ### get_fixed Source: https://experimental-design.github.io/bofire/docs/reference/data_models.domain.features.Inputs.html Gets all features in the Inputs object that are marked as fixed and returns them as a new Inputs object. ```APIDOC ## get_fixed ### Description Gets all features in `self` that are fixed and returns them as new. ### Method GET ### Endpoint /inputs/fixed ### Response #### Success Response (200) - **fixed_inputs** (Inputs) - A new Inputs object containing only the fixed features. ``` -------------------------------- ### Get Constraints DataFrame Source: https://experimental-design.github.io/bofire/docs/reference/data_models.domain.constraints.Constraints.html Obtain a tabular overview of all constraints within the domain as a pandas DataFrame. ```python data_models.domain.constraints.Constraints.get_reps_df() ``` -------------------------------- ### Prioritize Feasible Experiments with StepwiseStrategy Source: https://experimental-design.github.io/bofire/docs/userguides/strategies.html Combine RandomStrategy for initial exploration, then SoboStrategy with qLogPF to find feasible experiments, and finally a standard SoboStrategy for optimization. This is useful when output constraints must be met. ```python import bofire.strategies.api as strategies from bofire.benchmarks.api import DTLZ2 from bofire.data_models.acquisition_functions.api import qLogPF from bofire.data_models.objectives.api import MaximizeSigmoidObjective from bofire.data_models.strategies.api import ( AlwaysTrueCondition, FeasibleExperimentCondition, NumberOfExperimentsCondition, RandomStrategy, SoboStrategy, Step, StepwiseStrategy, ) # create a domain with one output constraint by assigning a MaximizeSigmoidObjective # to the output with key "f_1" domain = DTLZ2(dim=6).domain domain.outputs.get_by_key("f_1").objective = MaximizeSigmoidObjective( tp=0.5, steepness=100 ) strategy_data = StepwiseStrategy( domain=domain, steps=[ Step( strategy_data=RandomStrategy(domain=domain), condition=NumberOfExperimentsCondition(n_experiments=10), ), Step( strategy_data=SoboStrategy(domain=domain, acquisition_function=qLogPF()), condition=FeasibleExperimentCondition(n_required_feasible_experiments=1), ), Step( strategy_data=SoboStrategy(domain=domain), condition=AlwaysTrueCondition() ), ], ) strategy = strategies.map(strategy_data) ``` -------------------------------- ### Setup and Serialize Random Forest Surrogate Source: https://experimental-design.github.io/bofire/docs/tutorials/serialization/models_serial.html Demonstrates setting up a RandomForestSurrogate model with specified inputs, outputs, and random state, then generating its JSON specification. Ensure `input_features` and `output_features` are defined. ```python surrogate_data = RandomForestSurrogate( inputs=input_features, outputs=output_features, random_state=42, ) ``` ```python jspec = surrogate_data.model_dump_json() ``` -------------------------------- ### CategoricalInput Get Possible Categories Source: https://experimental-design.github.io/bofire/docs/reference/data_models.features.api.html Determines the superset of categories that can be used in optimization, based on experimental data. ```python data_models.features.api.CategoricalInput.get_possible_categories(values) ```