Skip to content

experiment_manager

BOExperimentManager

BOExperimentManager(input_details: list[dict[str, Any]], initial_experiments: DataFrame, db_path: str, strategy_type: str = 'sobo', kernel: str = 'rbf', objective_names: list[str] | None = None, minimize: bool | list[bool] = False, surrogate_type: str = 'GP', acquisition_function: str = 'qUCB', n_raw_samples: int = 64, n_restarts: int = 15, adaptive_acquisition: bool = False, beta: float | None = None, descriptor_method: str = 'exhaustive', n_constant_evaluations: int = 1000, constant_aggregation_strategy: str = 'mean', constant_aggregation_top_k: int = 50, constant_aggregation_temperature: float = 0.7, n_eval_const_samples: int | None = None, validate_training_bounds: bool = True, use_data_bounds: bool = False, ref_point: list[float] | None = None, scalarization_fn: Any | None = None, excel_path: str = '', sheet_name: str = 'Sheet1', log_file: str = 'bo_experiment.log', **kwargs: Any)

Multi-objective Bayesian Optimization Experiment Manager using BOtorch.

A comprehensive framework for Bayesian optimization that supports both single and multi-objective optimization with various strategies, kernels, and acquisition functions.

Supported Variable Types
  • 'continuous': Regular continuous variables with bounds
  • 'categorical': Discrete categorical variables (one-hot encoded)
  • 'categorical_descr': Discrete categorical variables with fixed descriptors Supports optional 'data_kw_include' to limit optimization to categories with specific keywords
  • 'categorical_descr_continuous': Continuous VAE latent space variables

Examples:

Basic usage for multi-objective optimization:

# Initialize the manager
manager = BOExperimentManager(
    input_details=[
        {"name": "temperature", "type": "continuous", "bounds": (20, 100)},
        {"name": "pressure", "type": "continuous", "bounds": (1, 10)}
    ],
    initial_experiments=df,
    db_path="experiments.db",
    objective_names=["yield", "selectivity"],
    strategy_type="mobo_pareto"
)

# Get new experiment suggestions
suggestions = manager.suggest_experiments(batch_size=5)

Parameters:

Name Type Description Default
input_details list[dict[str, Any]]

List of dictionaries specifying input variables. Each dict should contain 'name', 'type', 'bounds', and optionally 'categories', 'data', or 'step'.

required
initial_experiments DataFrame

DataFrame containing initial experimental data with input variables and objective columns.

required
db_path str

Path to database file for storing experimental data and results.

required
strategy_type str

Bayesian optimization strategy. Options: - "sobo": Single-objective optimization - "mobo_pareto": Pareto-based multi-objective optimization (default for >1 objective) - "mobo_additive": Additive scalarization (weighted sum) - "mobo_multiplicative": Multiplicative scalarization (weighted product) - "mobo_custom": Custom scalarization via user-supplied callable (scalarization_fn)

'sobo'
kernel str

Kernel type for Gaussian Process. Options: - "rbf": Hvarfner RBF kernel with high-dimensional initialization (default) - "matern": High-dimensional Matern 5/2 kernel - "matern_standard": Standard Matern 5/2 kernel with ARD

'rbf'
objective_names list[str] | None

List of column names in initial_experiments that correspond to objectives.

None
minimize bool | list[bool]

Whether to minimize objectives. Can be: - bool: Same optimization direction for all objectives (True=minimize, False=maximize) - List[bool]: Per-objective optimization direction (True=minimize, False=maximize) Default is True (minimize all objectives). BoTorch assumes maximization internally, so minimization objectives will have their Y values negated during training.

False
surrogate_type str

Type of surrogate model. Currently only supports "GP" (Gaussian Process).

'GP'
acquisition_function str

Acquisition function type. Options depend on strategy: - Single-objective: "qEI", "qLogEI", "qUCB" - Multi-objective: "qNEHVI", "qLogNEHVI"

'qUCB'
n_raw_samples int

Number of raw samples used for acquisition function optimization.

64
n_restarts int

Number of random restarts for acquisition function optimization.

15
adaptive_acquisition bool

Enable adaptive acquisition function selection (single-objective only).

False
beta float | None

Custom beta parameter for Upper Confidence Bound (UCB) acquisition function. If None, uses default (2.0) or adaptive beta when adaptive_acquisition=True.

None
descriptor_method str

Categorical descriptor handling ("continuous" or "exhaustive") - "continuous": Fast continuous optimization in descriptor space - "exhaustive": True mixed variable optimization with all categorical combinations (default)

'exhaustive'
n_constant_evaluations int

Number of different values to evaluate per constant variable (default: 50)

1000
constant_aggregation_strategy str

How to aggregate acquisition values for constant selection: - "mean": Average acquisition values (default, balanced) - "max": Maximum acquisition values (high-risk, high-reward) - "sum": Sum of acquisition values (similar to mean but different scaling) - "softmax": Weighted sum using softmax on top-k values (emphasizes having multiple high values)

'mean'
constant_aggregation_top_k int

For softmax aggregation, number of top acquisition values to consider (default: 50). This focuses the selection on the best-performing points. Should be set close to your batch size.

50
constant_aggregation_temperature float

For softmax aggregation, temperature parameter (default: 0.7). Lower values (e.g., 0.1-0.5) give more weight to the highest values. Higher values (e.g., 2.0-5.0) distribute weight more evenly across top-k points.

0.7
n_eval_const_samples int | None

Number of evaluation samples for constant variable selection. If None (default), uses min(1000, n_raw_samples * 2). If specified, uses this exact number of samples for evaluating constant variables.

None
validate_training_bounds bool

Whether to validate that training data is within optimization bounds

True
use_data_bounds bool

Whether to expand optimization bounds to accommodate both training data and input_details bounds. When True, bounds are expanded to ensure all training data is within bounds while preserving the intended optimization ranges from input_details. Useful when training data extends beyond specified bounds.

False
ref_point list[float] | None

Optional reference point for multi-objective optimization. If None, computed automatically. Should be a list of floats with length equal to number of objectives.

None
excel_path str

Optional path to an Excel file containing new experiments to load and integrate into the database.

''
sheet_name str

Sheet name in the Excel file to read from (default: "Sheet1").

'Sheet1'
log_file str

Name of the log file for experiment logging (default: "bo_experiment.log"). All logging output will be written to this file instead of console.

'bo_experiment.log'
**kwargs Any

Additional keyword arguments passed to AdaptiveAcquisitionManager when adaptive_acquisition=True.

{}

Raises:

Type Description
ValueError

If strategy and acquisition function are incompatible, if required variables are missing from experimental data, if adaptive acquisition is enabled for multi-objective optimization, or if data validation fails.

Notes
  • For multi-objective optimization, use strategy_type="mobo_pareto" for true Pareto optimization, or "mobo_additive"/"mobo_multiplicative" for scalarization approaches.
  • High-dimensional problems (>10 dimensions) should use "rbf" or "matern" kernels for better performance.
  • Adaptive acquisition is only supported for single-objective optimization and scalarization strategies.
  • The reference point for multi-objective optimization should represent slightly worse values than the worst observed objectives.

Methods:

Name Description
get_current_acquisition_strategy

Return current acquisition strategy metadata.

get_adaptive_acquisition_function

Return current adaptive acquisition function (falls back to fixed).

get_adaptive_beta

Return current beta value for adaptive acquisition (or fixed default).

_validate_configuration

Validate the configuration parameters.

_prepare_training_data

Prepare training data using the variable processor.

_recalculate_training_bounds_from_data

Recalculate training bounds based on training data while preserving optimization space.

_normalize_training_data

Normalize training data using appropriate bounds based on use_data_bounds setting.

_create_model

Create and fit the GP model(s) using ModelFactory.

_fit_model

Fit the GP model using MLE - delegated to ModelFactory.

_create_acquisition_function

Create the acquisition function.

_create_mobo_acquisition_function

Create multi-objective acquisition function based on strategy.

_compute_reference_point

Compute a robust reference point for (Log)NEHVI/EHVI.

_get_pruned_baseline

Prune baseline design points for (Log)NEHVI/EHVI efficiency.

_create_scalarized_acquisition

Create scalarized acquisition function for additive/multiplicative strategies.

_create_single_objective_acquisition

Create single-objective acquisition function based on user's choice.

_apply_step_constraints

Apply step size constraints to continuous variables using consistent normalization bounds.

_suggest_batch_candidates

Suggest a batch of candidate experiments.

_log_candidate_analysis

Log analysis of candidate diversity and unique values per variable.

_suggest_batch_with_constants

Mixed variable optimization with categorical descriptors.

_get_categorical_descriptor_combinations

Create fixed_features_list for categorical descriptor variables.

_snap_categorical_descriptors_to_discrete_choices

Snap continuous categorical descriptor values to their nearest discrete choices.

_select_optimal_constant_features

Select optimal values for constant variables.

_create_constant_variable_combinations

Create all combinations of constant variable values for batch evaluation.

_create_stepped_evaluation_grid

Create evaluation grid for a variable based on its step specification.

_unnormalize_single_value

Convert a normalized value back to actual variable space.

_get_constant_variable_fixed_features

Create fixed features dict for constant variables using optimal selection.

_expand_porous_liquid_to_components

Expand porous_liquid strings into component columns with IL names and CAS number lookup.

_reorder_experiment_columns

Reorder DataFrame columns to group related components together and remove porous_liquid.

_convert_candidates_to_experiments

Convert normalized candidate points to experimental parameter format using VariableProcessor.

suggest_experiments

Suggest next batch of experiments using Bayesian optimization.

update_with_new_data

Incorporate new experimental results into the optimization framework.

load_new_experiments_from_excel

Load new experiments from an Excel file and update the internal DataFrame.

get_pareto_front

Extract the Pareto front (non-dominated solutions) from the training data.

get_trained_model

Create and fit the GP model(s) on training data.

predict_with_model

Generate predictions using a pre-trained model.

get_model_predictions

Generate Gaussian Process model predictions for test points.

_convert_dataframe_to_tensor

Convert DataFrame to tensor format matching training data.

Attributes:

Name Type Description
input_details
input_variables
initial_experiments
db_path
strategy_type
kernel
objective_names
minimize
surrogate_type
acquisition_function
n_raw_samples
n_restarts
validate_training_bounds
use_data_bounds
adaptive_acquisition
beta
descriptor_method
ref_point
scalarization_fn
excel_path
sheet_name
df_new_experiments
n_constant_evaluations
constant_aggregation_strategy
constant_aggregation_top_k
constant_aggregation_temperature
n_eval_const_samples
adaptive_manager
variable_processor
input_dim
bounds
original_bounds
training_bounds
optim_helper
model_factory

Attributes

input_details instance-attribute

input_details = input_details

input_variables instance-attribute

input_variables = [(InputVariable(**detail)) for detail in input_details]

initial_experiments instance-attribute

initial_experiments = copy()

db_path instance-attribute

db_path = db_path

strategy_type instance-attribute

strategy_type = StrategyType(strategy_type)

kernel instance-attribute

kernel = kernel

objective_names instance-attribute

objective_names = objective_names

minimize instance-attribute

minimize = [minimize] * len(objective_names)

surrogate_type instance-attribute

surrogate_type = surrogate_type

acquisition_function instance-attribute

acquisition_function = AcquisitionFunction(acquisition_function)

n_raw_samples instance-attribute

n_raw_samples = n_raw_samples

n_restarts instance-attribute

n_restarts = n_restarts

validate_training_bounds instance-attribute

validate_training_bounds = validate_training_bounds

use_data_bounds instance-attribute

use_data_bounds = use_data_bounds

adaptive_acquisition instance-attribute

adaptive_acquisition = adaptive_acquisition

beta instance-attribute

beta = beta

descriptor_method instance-attribute

descriptor_method = lower()

ref_point instance-attribute

ref_point = tensor(ref_point, dtype=dtype, device=device) if ref_point is not None else None

scalarization_fn instance-attribute

scalarization_fn = scalarization_fn

excel_path instance-attribute

excel_path = excel_path

sheet_name instance-attribute

sheet_name = sheet_name

df_new_experiments instance-attribute

df_new_experiments = load_new_experiments_from_excel(excel_path=excel_path, sheet_name=sheet_name)

n_constant_evaluations instance-attribute

n_constant_evaluations = max(3, n_constant_evaluations)

constant_aggregation_strategy instance-attribute

constant_aggregation_strategy = constant_aggregation_strategy

constant_aggregation_top_k instance-attribute

constant_aggregation_top_k = constant_aggregation_top_k

constant_aggregation_temperature instance-attribute

constant_aggregation_temperature = constant_aggregation_temperature

n_eval_const_samples instance-attribute

n_eval_const_samples = n_eval_const_samples

adaptive_manager instance-attribute

adaptive_manager = AdaptiveAcquisitionManager(**kwargs)

variable_processor instance-attribute

variable_processor = VariableProcessor(input_variables)

input_dim instance-attribute

input_dim = input_dim

bounds instance-attribute

bounds = bounds

original_bounds instance-attribute

original_bounds = clone()

training_bounds instance-attribute

training_bounds = clone()

optim_helper instance-attribute

optim_helper = OptimizationHelper(variable_processor, n_raw_samples=n_raw_samples, n_restarts=n_restarts, normalization_bounds=normalization_bounds)

model_factory instance-attribute

model_factory = ModelFactory(input_dim, kernel)

Functions

get_current_acquisition_strategy

get_current_acquisition_strategy() -> dict[str, Any]

Return current acquisition strategy metadata.

For adaptive single-objective (or scalarized) runs returns stage, function, beta. For non-adaptive setups returns the fixed acquisition configuration.

get_adaptive_acquisition_function

get_adaptive_acquisition_function() -> str

Return current adaptive acquisition function (falls back to fixed).

get_adaptive_beta

get_adaptive_beta() -> float

Return current beta value for adaptive acquisition (or fixed default).

_validate_configuration

_validate_configuration()

Validate the configuration parameters.

_prepare_training_data

_prepare_training_data()

Prepare training data using the variable processor.

_recalculate_training_bounds_from_data

_recalculate_training_bounds_from_data()

Recalculate training bounds based on training data while preserving optimization space.

When use_data_bounds=True, we expand bounds to include training data but ensure the optimization space (original bounds) is still accessible for candidate generation.

_normalize_training_data

_normalize_training_data()

Normalize training data using appropriate bounds based on use_data_bounds setting.

_create_model

_create_model() -> SingleTaskGP | ModelListGP

Create and fit the GP model(s) using ModelFactory.

_fit_model

_fit_model(model)

Fit the GP model using MLE - delegated to ModelFactory.

_create_acquisition_function

_create_acquisition_function(model)

Create the acquisition function.

_create_mobo_acquisition_function

_create_mobo_acquisition_function(model: Any, current_acq_func: Any) -> Any

Create multi-objective acquisition function based on strategy.

Adds robustness vs prior implementation by
  • Using _compute_reference_point to ensure strictly dominated ref point
  • Pruning baseline points to nondominated set (with guards) for NEHVI variants

_compute_reference_point

_compute_reference_point(Y: Tensor, buffer: float = 0.1) -> Tensor

Compute a robust reference point for (Log)NEHVI/EHVI.

The reference point must be strictly dominated by all observed objective vectors to yield non-zero hypervolume. Using raw minima can cause the hypervolume improvement to collapse to ~0 if a new point exactly matches an observed minimum (floating point ties). We add a configurable buffer proportional to each objective's observed range and a tiny epsilon shift.

Formula (per objective j): range_j = max_j(Y) - min_j(Y) safe_rng = max(range_j, 1e-6) # avoid degenerate zero range ref_j = min_j(Y) - buffer * safe_rng - 1e-8

Rationale
  • Proportional offset (buffer * range) scales with objective spread.
  • Clamp keeps constant objectives (range ≈ 0) producing a small finite margin rather than identical minima (avoids zero volume).
  • Extra 1e-8 enforces strict dominance in float64.

Parameters:

Name Type Description Default
Y Tensor

Tensor of shape (n, m) with observed (transformed) objective values (all assumed maximization at this stage).

required
buffer float

Fraction of each objective's observed range to subtract. Typical values: 0.05-0.2. Higher = more conservative ref point.

0.1

Returns:

Name Type Description
ref_point Tensor

Tensor (m,) strictly dominated by all rows of Y.

Raises:

Type Description
ValueError

If Y is empty.

Edge Cases
  • Constant objectives: range -> 0 ⇒ safe_rng = 1e-6 ⇒ small margin.
  • Single observation: min == max, still produces ref below the point.

_get_pruned_baseline

_get_pruned_baseline(X_baseline: Tensor, Y: Tensor) -> Tensor

Prune baseline design points for (Log)NEHVI/EHVI efficiency.

Hypervolume-based acquisition functions scale poorly with large baselines because they perform Monte Carlo integration and partitioning over the nondominated front. Retaining only nondominated points preserves the Pareto frontier while reducing computation. We also cap the final set size to a fixed maximum via random subsampling to bound worst-case cost.

Steps
  1. Identify nondominated indices with is_non_dominated on Y.
  2. If fewer than 2 nondominated points, return original baseline (partitioning degenerates; small cost anyway).
  3. If nondominated count > max_baseline (256), randomly downsample to max_baseline points (uniform; stratification unnecessary given frontier size, keeps logic simple and fast).

Parameters:

Name Type Description Default
X_baseline Tensor

Tensor (n, d) of baseline inputs (normalized)

required
Y Tensor

Tensor (n, m) of corresponding objective values (all maximization)

required

Returns:

Type Description
Tensor

Tensor (k, d) of pruned baseline points, k <= n.

Notes
  • Deterministic alternative (e.g., farthest-point) could be added if reproducibility of pruning is critical; random is adequate now.
  • Caller maintains alignment: only X is returned because acquisition constructors recompute Y as needed or accept separate Y tensors.

_create_scalarized_acquisition

_create_scalarized_acquisition(model: Any, strategy: str) -> Any

Create scalarized acquisition function for additive/multiplicative strategies.

_create_single_objective_acquisition

_create_single_objective_acquisition(model, best_f)

Create single-objective acquisition function based on user's choice.

_apply_step_constraints

_apply_step_constraints(candidates: Tensor) -> Tensor

Apply step size constraints to continuous variables using consistent normalization bounds.

_suggest_batch_candidates

_suggest_batch_candidates(batch_size: int, const_vars: list[str] | None = None) -> Tensor

Suggest a batch of candidate experiments.

_log_candidate_analysis

_log_candidate_analysis(candidates: Tensor)

Log analysis of candidate diversity and unique values per variable.

_suggest_batch_with_constants

_suggest_batch_with_constants(acq_func, batch_size: int, const_vars: list[str], acqf_maxiter: int = 2000, acqf_method: str = 'L-BFGS-B') -> Tensor

Mixed variable optimization with categorical descriptors.

This implementation: - descriptor_method="continuous": Fast continuous optimization in descriptor space (default) - descriptor_method="exhaustive": True mixed variable optimization with categorical combinations

_get_categorical_descriptor_combinations

_get_categorical_descriptor_combinations() -> list[dict[int, float]]

Create fixed_features_list for categorical descriptor variables.

This method creates all possible combinations of categorical descriptor values for use with optimize_acqf_mixed. If data_kw_include is specified for a categorical_descr variable, only categories containing those keywords will be used for optimization (training still uses all categories).

_snap_categorical_descriptors_to_discrete_choices

_snap_categorical_descriptors_to_discrete_choices(candidates: Tensor) -> Tensor

Snap continuous categorical descriptor values to their nearest discrete choices. This handles categorical descriptor variables in "continuous" mode.

_select_optimal_constant_features

_select_optimal_constant_features(acq_func: Any, const_vars: list[str]) -> dict[int, float]

Select optimal values for constant variables.

This implements a two-step optimization: 1. Evaluate acquisition function for different constant variable values 2. Select best values based on aggregated acquisition function values

Parameters:

Name Type Description Default
acq_func Any

The acquisition function to evaluate

required
const_vars list[str]

List of variable names to be held constant

required

Returns:

Type Description
dict[int, float]

Dictionary mapping variable indices to optimal normalized values

_create_constant_variable_combinations

_create_constant_variable_combinations(const_var_indices: list[int]) -> list[dict[int, float]]

Create all combinations of constant variable values for batch evaluation.

Parameters:

Name Type Description Default
const_var_indices list[int]

List of variable indices that should be constant

required

Returns:

Type Description
list[dict[int, float]]

List of dictionaries, each mapping variable indices to their values

_create_stepped_evaluation_grid

_create_stepped_evaluation_grid(var: Any, var_idx: int) -> Tensor

Create evaluation grid for a variable based on its step specification.

Parameters:

Name Type Description Default
var Any

InputVariable object with bounds and step information

required
var_idx int

Index of the variable in the bounds tensor

required

Returns:

Type Description
Tensor

Tensor of normalized evaluation values

_unnormalize_single_value

_unnormalize_single_value(normalized_value: float, var: Any) -> float

Convert a normalized value back to actual variable space.

Parameters:

Name Type Description Default
normalized_value float

Value in [0,1] normalized space

required
var Any

InputVariable object with bounds

required

Returns:

Type Description
float

Value in actual variable space

_get_constant_variable_fixed_features

_get_constant_variable_fixed_features(const_vars: list[str], acq_func: Any | None = None, use_optimal_selection: bool = True) -> dict[int, float]

Create fixed features dict for constant variables using optimal selection.

Parameters:

Name Type Description Default
const_vars list[str]

List of variable names to be held constant

required
acq_func Any | None

Acquisition function for optimal selection

None
use_optimal_selection bool

Whether to use optimal selection (parameter kept for compatibility)

True

Returns:

Type Description
dict[int, float]

Dictionary mapping variable indices to their fixed values

_expand_porous_liquid_to_components

_expand_porous_liquid_to_components(porous_liquid_values: Series) -> DataFrame

Expand porous_liquid strings into component columns with IL names and CAS number lookup.

Parameters:

Name Type Description Default
porous_liquid_values Series

Series of porous_liquid strings (format: "cation.anion.mof")

required

Returns:

Type Description
DataFrame

DataFrame with columns: il_cation_smiles, il_cation_name, il_anion_smiles, il_anion_name, mof_name, il_cas_no

_reorder_experiment_columns

_reorder_experiment_columns(df: DataFrame) -> DataFrame

Reorder DataFrame columns to group related components together and remove porous_liquid.

Parameters:

Name Type Description Default
df DataFrame

DataFrame with experiment suggestions

required

Returns:

Type Description
DataFrame

DataFrame with reordered columns (without porous_liquid)

Notes

Order: non-component columns (in original order), then component columns: il_cation_smiles, il_cation_name, il_anion_smiles, il_anion_name, mof_name

_convert_candidates_to_experiments

_convert_candidates_to_experiments(candidates: Tensor) -> DataFrame

Convert normalized candidate points to experimental parameter format using VariableProcessor.

suggest_experiments

suggest_experiments(batch_size: int, const_batch_properties: list[str] | None = None, bo_iter: int | None = None) -> DataFrame

Suggest next batch of experiments using Bayesian optimization.

This method performs the complete Bayesian optimization workflow: 1. Fits Gaussian Process model(s) to existing data 2. Creates appropriate acquisition function based on strategy 3. Optimizes acquisition function to find promising candidates 4. Applies variable constraints and converts to experimental format

For batch optimization with constant variables, uses two-step optimization: 1. Evaluates acquisition function across constant variable combinations 2. Selects optimal constant values and optimizes remaining variables

Parameters:

Name Type Description Default
batch_size int

Number of experiments to suggest. Must be > 0.

required
const_batch_properties list[str] | None

Optional list of variable names that should have identical values across all suggested experiments. Useful for batch experiments with shared conditions.

None
bo_iter int | None

Optional BO iteration number to include in the output DataFrame. If not provided and db_path is set, automatically determined as max(bo_iter) + 1 from the experiments table.

None

Returns:

Type Description
DataFrame

DataFrame containing suggested experiments with columns for each input variable.

DataFrame

Each row represents one suggested experiment with values in the original

DataFrame

(unnormalized) variable space.

Raises:

Type Description
ValueError

If batch_size <= 0 or if const_batch_properties contains variable names not found in input_details.

Examples:

>>> # Basic batch suggestion
>>> suggestions = manager.suggest_experiments(batch_size=5)
>>> # Batch with constant temperature and pressure
>>> suggestions = manager.suggest_experiments(
...     batch_size=10, 
...     const_batch_properties=["temperature", "pressure"]
... )
Notes
  • For constant variables, optimal values are selected using grid search over the acquisition function
  • Step constraints are automatically applied to continuous variables
  • Categorical descriptor variables are snapped to nearest discrete choices when using descriptor_method="continuous"

update_with_new_data

update_with_new_data(new_experiments: DataFrame)

Incorporate new experimental results into the optimization framework.

Adds new experimental data to the existing dataset and reprocesses all training data. This allows for iterative optimization where new experiments are performed based on previous suggestions and their results are fed back into the model.

Parameters:

Name Type Description Default
new_experiments DataFrame

DataFrame containing new experimental results. Must have the same columns as initial_experiments, including all input variables and objectives.

required

Raises:

Type Description
ValueError

If new_experiments has incompatible columns or if data validation fails for the combined dataset.

Examples:

>>> # Add results from batch of suggested experiments
>>> new_results = pd.DataFrame({
...     'temperature': [25, 50],
...     'pressure': [2, 5],
...     'yield': [0.8, 0.9],
...     'selectivity': [0.7, 0.6]
... })
>>> manager.update_with_new_data(new_results)
>>> # Now ready for next round of suggestions
Notes
  • Training data is automatically reprocessed and renormalized
  • Model bounds are recalculated if validate_training_bounds=True

load_new_experiments_from_excel

load_new_experiments_from_excel(excel_path: str = '', sheet_name: str = 'Sheet1') -> DataFrame

Load new experiments from an Excel file and update the internal DataFrame.

This method reads experiment data from an Excel file and integrates it into the database, avoiding duplicate entries. Useful for incorporating new experimental results obtained outside the optimization loop.

Parameters:

Name Type Description Default
excel_path str

Path to the Excel file containing new experiments. If empty or invalid, returns empty DataFrame.

''
sheet_name str

Sheet name in the Excel file to read from.

'Sheet1'

Returns:

Type Description
DataFrame

DataFrame containing the new experiments that were loaded,

DataFrame

or empty DataFrame if no valid file was provided or loading failed.

Notes
  • Only new rows (not already in the database) are added
  • Database is automatically updated with new experiments
  • Excel file must have the same column structure as existing data

Examples:

>>> # Load new experimental results from Excel
>>> new_data = manager.load_new_experiments_from_excel(
...     excel_path="new_results.xlsx",
...     sheet_name="Experiments"
... )
>>> print(f"Loaded {len(new_data)} new experiments")

get_pareto_front

get_pareto_front() -> DataFrame

Extract the Pareto front (non-dominated solutions) from the training data.

The Pareto front consists of all experiments where no other experiment is strictly better in all objectives. For maximization problems, this represents the trade-off frontier between competing objectives.

Returns:

Type Description
DataFrame

DataFrame containing only the Pareto-optimal experiments from the

DataFrame

training data, with the same columns as initial_experiments.

Raises:

Type Description
ValueError

If fewer than 2 objectives are defined (Pareto front requires multi-objective optimization).

Notes
  • Assumes all objectives are to be maximized
  • For minimization objectives, negate values before using this method
  • The returned DataFrame may be empty if all points are dominated
  • Points are considered non-dominated using BOtorch's is_non_dominated function

get_trained_model

get_trained_model()

Create and fit the GP model(s) on training data.

Returns:

Type Description

Trained GP model (SingleTaskGP for single objective, ModelListGP for multi-objective)

predict_with_model

predict_with_model(model, X_test: DataFrame) -> dict[str, ndarray]

Generate predictions using a pre-trained model.

This method allows predictions without retraining, which is essential for proper model evaluation (train once, evaluate on multiple datasets).

Use original bounds for training data normalization

Args: model: Pre-trained GP model (from get_trained_model()) X_test: DataFrame containing test experiments

Returns:

Type Description
dict[str, ndarray]

Dictionary mapping prediction types to arrays:

dict[str, ndarray]
  • For single objective: "{objective}_mean", "{objective}_var"
dict[str, ndarray]
  • For multiple objectives: "{obj1}_mean", "{obj1}_var", "{obj2}_mean", "{obj2}_var", ...

get_model_predictions

get_model_predictions(X_test: DataFrame) -> dict[str, ndarray]

Generate Gaussian Process model predictions for test points.

⚠️ WARNING: This method creates and fits a NEW model for each call! For proper model evaluation (train once, test multiple times), use: 1. get_trained_model() to train the model once 2. predict_with_model(model, data) for predictions

This method is suitable for: - Single predictions where retraining is acceptable - Exploration of response surfaces - NOT for proper train/test evaluation methodology

Parameters:

Name Type Description Default
X_test DataFrame

DataFrame containing test experiments with the same columns as the input variables defined in input_details. Each row represents one test point.

required

Returns:

Type Description
dict[str, ndarray]

Dictionary mapping prediction types to arrays:

dict[str, ndarray]
  • For single objective: "{objective}_mean", "{objective}_var"
dict[str, ndarray]
  • For multiple objectives: "{obj1}_mean", "{obj1}_var", "{obj2}_mean", "{obj2}_var", ...
dict[str, ndarray]

Each array has length equal to the number of rows in X_test.

Raises:

Type Description
ValueError

If X_test contains columns not matching input variable names or if required variables are missing.

Examples:

>>> test_df = pd.DataFrame({
...     'temperature': [25, 50, 75],
...     'pressure': [2, 5, 8]
... })
>>> predictions = manager.get_model_predictions(test_df)
>>> print(predictions.keys())  # ['yield_mean', 'yield_var', 'selectivity_mean', 'selectivity_var']

_convert_dataframe_to_tensor

_convert_dataframe_to_tensor(df: DataFrame) -> Tensor

Convert DataFrame to tensor format matching training data.