Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make the BoFire Data Models OpenAI compatible #495

Merged
merged 3 commits into from
Jan 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions bofire/benchmarks/detergent.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,11 @@ def __init__(self):

self._domain = Domain.from_lists(
inputs=[
ContinuousInput(key="x1", bounds=(0.0, 0.2)),
ContinuousInput(key="x2", bounds=(0.0, 0.3)),
ContinuousInput(key="x3", bounds=(0.02, 0.2)),
ContinuousInput(key="x4", bounds=(0.0, 0.06)),
ContinuousInput(key="x5", bounds=(0.0, 0.04)),
ContinuousInput(key="x1", bounds=[0.0, 0.2]),
ContinuousInput(key="x2", bounds=[0.0, 0.3]),
ContinuousInput(key="x3", bounds=[0.02, 0.2]),
ContinuousInput(key="x4", bounds=[0.0, 0.06]),
ContinuousInput(key="x5", bounds=[0.0, 0.04]),
],
outputs=[ContinuousOutput(key=f"y{i+1}") for i in range(5)],
constraints=[
Expand Down
30 changes: 15 additions & 15 deletions bofire/benchmarks/multi.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def __init__(self, dim: PositiveInt, num_objectives: PositiveInt = 2, **kwargs):

inputs = []
for i in range(self.dim):
inputs.append(ContinuousInput(key="x_%i" % (i), bounds=(0, 1)))
inputs.append(ContinuousInput(key="x_%i" % (i), bounds=[0, 1]))
outputs = []
self.k = self.dim - self.num_objectives + 1
for i in range(self.num_objectives):
Expand Down Expand Up @@ -140,8 +140,8 @@ def __init__(self, constraints: bool = True, **kwargs):
self._domain = Domain(
inputs=Inputs(
features=[
ContinuousInput(key="x1", bounds=(0, 5)),
ContinuousInput(key="x2", bounds=(0, 3)),
ContinuousInput(key="x1", bounds=[0, 5]),
ContinuousInput(key="x2", bounds=[0, 3]),
],
),
outputs=Outputs(
Expand Down Expand Up @@ -187,8 +187,8 @@ def __init__(self, **kwargs):
self._domain = Domain(
inputs=Inputs(
features=[
ContinuousInput(key="x1", bounds=(0, math.pi)),
ContinuousInput(key="x2", bounds=(0, math.pi)),
ContinuousInput(key="x1", bounds=[0, math.pi]),
ContinuousInput(key="x2", bounds=[0, math.pi]),
],
),
outputs=Outputs(
Expand Down Expand Up @@ -293,13 +293,13 @@ def __init__(self, C_i: Optional[np.ndarray] = None, **kwargs):
# Decision variables
# "residence time in minutes"
inputs = [
ContinuousInput(key="tau", bounds=(0.5, 2)),
ContinuousInput(key="tau", bounds=[0.5, 2]),
# "equivalents of pyrrolidine"
ContinuousInput(key="equiv_pldn", bounds=(1, 5)),
ContinuousInput(key="equiv_pldn", bounds=[1, 5]),
# "concentration of 2,4 dinitrofluorobenenze at reactor inlet (after mixing) in M"
ContinuousInput(key="conc_dfnb", bounds=(0.1, 0.5)),
ContinuousInput(key="conc_dfnb", bounds=[0.1, 0.5]),
# "Reactor temperature in degrees celsius"
ContinuousInput(key="temperature", bounds=(30, 120)),
ContinuousInput(key="temperature", bounds=[30, 120]),
]
# Objectives
# "space time yield (kg/m^3/h)"
Expand Down Expand Up @@ -442,7 +442,7 @@ def __init__(self, n_inputs=30, **kwargs):
super().__init__(**kwargs)
self.n_inputs = n_inputs
inputs = [
ContinuousInput(key=f"x{i+1}", bounds=(0, 1)) for i in range(n_inputs)
ContinuousInput(key=f"x{i+1}", bounds=[0, 1]) for i in range(n_inputs)
]
inputs = Inputs(features=inputs)
outputs = [
Expand Down Expand Up @@ -550,11 +550,11 @@ def __init__(
],
),
# "base equivalents"
ContinuousInput(key="base_eq", bounds=(1, 2.5)),
ContinuousInput(key="base_eq", bounds=[1, 2.5]),
# "Reactor temperature in degrees celsius"
ContinuousInput(key="temperature", bounds=(30, 100)),
ContinuousInput(key="temperature", bounds=[30, 100]),
# "residence time in seconds (s)"
ContinuousInput(key="t_res", bounds=(60, 1800)),
ContinuousInput(key="t_res", bounds=[60, 1800]),
]

input_preprocessing_specs = {
Expand All @@ -566,11 +566,11 @@ def __init__(
outputs = [
ContinuousOutput(
key="yield",
objective=MaximizeObjective(w=1.0, bounds=(0.0, 1.0)),
objective=MaximizeObjective(w=1.0, bounds=[0.0, 1.0]),
),
ContinuousOutput(
key="cost",
objective=MinimizeObjective(w=1.0, bounds=(0.0, 1.0)),
objective=MinimizeObjective(w=1.0, bounds=[0.0, 1.0]),
),
]
self.ref_point = {"yield": 0.0, "cost": 1.0}
Expand Down
50 changes: 23 additions & 27 deletions bofire/benchmarks/single.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ def __init__(
# continuous input features
for d in range(self.dim):
input_feature_list.append(
ContinuousInput(key=f"x_{d+1}", bounds=(self.lower, self.upper)),
ContinuousInput(key=f"x_{d+1}", bounds=[self.lower, self.upper]),
)

# Objective
Expand Down Expand Up @@ -179,7 +179,7 @@ def __init__(self, dim: int = 6, allowed_k: Optional[int] = None, **kwargs) -> N
self._domain = Domain(
inputs=Inputs(
features=[
ContinuousInput(key=f"x_{i}", bounds=(0, 1)) for i in range(dim)
ContinuousInput(key=f"x_{i}", bounds=[0, 1]) for i in range(dim)
],
),
outputs=Outputs(
Expand Down Expand Up @@ -235,7 +235,7 @@ def __init__(self, dim: int = 6, allowed_k: Optional[int] = None, **kwargs) -> N
self._domain = Domain(
inputs=Inputs(
features=[
ContinuousInput(key=f"x_{i}", bounds=(0, 1)) for i in range(dim)
ContinuousInput(key=f"x_{i}", bounds=[0, 1]) for i in range(dim)
]
),
outputs=Outputs(
Expand Down Expand Up @@ -291,27 +291,23 @@ def __init__(self, locality_factor: Optional[float] = None, **kwargs) -> None:
features=[
ContinuousInput(
key="x_1",
bounds=(-5.0, 10),
local_relative_bounds=(
(
0.5 * locality_factor,
0.5 * locality_factor,
)
if locality_factor is not None
else None
),
bounds=[-5.0, 10],
local_relative_bounds=[
0.5 * locality_factor,
0.5 * locality_factor,
]
if locality_factor is not None
else None,
),
ContinuousInput(
key="x_2",
bounds=(0.0, 15.0),
local_relative_bounds=(
(
1.5 * locality_factor,
1.5 * locality_factor,
)
if locality_factor is not None
else None
),
bounds=[0.0, 15.0],
local_relative_bounds=[
1.5 * locality_factor,
1.5 * locality_factor,
]
if locality_factor is not None
else None,
),
],
),
Expand Down Expand Up @@ -355,7 +351,7 @@ def __init__(self, **kwargs) -> None:
self._domain = Domain(
inputs=Inputs(
features=[
ContinuousInput(key=f"x_{i+1:02d}", bounds=(0, 1))
ContinuousInput(key=f"x_{i+1:02d}", bounds=[0, 1])
for i in range(30)
],
),
Expand Down Expand Up @@ -398,8 +394,8 @@ def __init__(self, use_constraints: bool = False, **kwargs):
self.use_constraints = use_constraints
inputs = []

inputs.append(ContinuousInput(key="x_1", bounds=(-6, 6)))
inputs.append(ContinuousInput(key="x_2", bounds=(-6, 6)))
inputs.append(ContinuousInput(key="x_1", bounds=[-6, 6]))
inputs.append(ContinuousInput(key="x_2", bounds=[-6, 6]))

objective = MinimizeObjective(w=1.0)
output_feature = ContinuousOutput(key="y", objective=objective)
Expand Down Expand Up @@ -472,8 +468,8 @@ def __init__(self, use_constraints: bool = False, **kwargs):
inputs = []

inputs.append(TaskInput(key="task_id", categories=["task_1", "task_2"]))
inputs.append(ContinuousInput(key="x_1", bounds=(-6, 6)))
inputs.append(ContinuousInput(key="x_2", bounds=(-6, 6)))
inputs.append(ContinuousInput(key="x_1", bounds=[-6, 6]))
inputs.append(ContinuousInput(key="x_2", bounds=[-6, 6]))

objective = MinimizeObjective(w=1.0)
output_feature = ContinuousOutput(key="y", objective=objective)
Expand Down Expand Up @@ -645,7 +641,7 @@ def __init__(
self._domain = Domain(
inputs=Inputs(
features=[
ContinuousInput(key=f"x_{i}", bounds=(0, 1))
ContinuousInput(key=f"x_{i}", bounds=[0, 1])
for i in range(self.dim)
],
),
Expand Down
2 changes: 1 addition & 1 deletion bofire/data_models/features/continuous.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class ContinuousInput(NumericalInput):

bounds: Bounds
local_relative_bounds: Optional[
Tuple[Annotated[float, Field(gt=0)], Annotated[float, Field(gt=0)]]
Annotated[List[Annotated[float, Field(gt=0)]], Field(min_items=2, max_items=2)] # type: ignore
] = None
stepsize: Optional[float] = None

Expand Down
7 changes: 4 additions & 3 deletions bofire/data_models/objectives/identity.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
from typing import Literal, Optional, Tuple, Union
from typing import Literal, Optional, Union

import numpy as np
import pandas as pd
from pydantic import field_validator

from bofire.data_models.objectives.objective import Objective, TWeight
from bofire.data_models.types import Bounds


class IdentityObjective(Objective):
Expand All @@ -17,9 +18,9 @@ class IdentityObjective(Objective):

"""

type: Literal["IdentityObjective"] = "IdentityObjective"
type: Literal["IdentityObjective"] = "IdentityObjective" # type: ignore
w: TWeight = 1
bounds: Tuple[float, float] = (0, 1)
bounds: Bounds = [0, 1]

@property
def lower_bound(self) -> float:
Expand Down
5 changes: 3 additions & 2 deletions bofire/data_models/types.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from collections.abc import Sequence
from typing import Annotated, Dict, List, Tuple, Union
from typing import Annotated, Dict, List, Union

from pydantic import AfterValidator, Field, PositiveInt

Expand Down Expand Up @@ -92,7 +92,8 @@ def validate_monotonically_increasing(sequence: Sequence[float]) -> Sequence[flo
]

Bounds = Annotated[
Tuple[float, float],
List[float],
Field(min_length=2, max_length=2),
AfterValidator(validate_monotonically_increasing),
]

Expand Down
2 changes: 1 addition & 1 deletion bofire/strategies/doe/objective.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def __init__(
else:
self.transform = MinMaxTransform(
inputs=self.domain.inputs,
feature_range=transform_range,
feature_range=tuple(transform_range), # type: ignore
)

self.n_experiments = n_experiments
Expand Down
8 changes: 4 additions & 4 deletions bofire/strategies/doe/utils_categorical_discrete.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ def NChooseKGroup_with_quantity(
# if we use_legacy_class is true this constraint will be added by the discrete_to_relaxable_domain_mapper function
pick_exactly_one_of_group_const = []
else:
category = [ContinuousInput(key=k, bounds=(0, 1)) for k in keys]
category = [ContinuousInput(key=k, bounds=[0, 1]) for k in keys]
pick_exactly_one_of_group_const = [
LinearEqualityConstraint(
features=list(keys),
Expand Down Expand Up @@ -293,7 +293,7 @@ def _generate_quantity_var_constr(
quantity_var = [
ContinuousInput(
key=unique_group_identifier + "_" + k + "_quantity",
bounds=(0, q[1]),
bounds=[0, q[1]],
)
for k, q in zip(keys, quantity_if_picked)
]
Expand Down Expand Up @@ -469,7 +469,7 @@ def NChooseKGroup(
# adding the new possible combinations to the list of keys
keys = combined_keys

category = [ContinuousInput(key=k, bounds=(0, 1)) for k in keys]
category = [ContinuousInput(key=k, bounds=[0, 1]) for k in keys]
pick_exactly_one_of_group_const = [
LinearEqualityConstraint(
features=list(keys),
Expand All @@ -489,7 +489,7 @@ def NChooseKGroup(
def generate_mixture_constraints(
keys: List[str],
) -> Tuple[LinearEqualityConstraint, List[ContinuousInput]]:
binary_vars = (ContinuousInput(key=x, bounds=(0, 1)) for x in keys)
binary_vars = (ContinuousInput(key=x, bounds=[0, 1]) for x in keys)

mixture_constraint = LinearEqualityConstraint(
features=keys,
Expand Down
2 changes: 1 addition & 1 deletion bofire/strategies/random.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ def _sample_with_nchooseks(
for key in u:
feat = domain.inputs.get_by_key(key=key)
assert isinstance(feat, ContinuousInput)
feat.bounds = (0, 0)
feat.bounds = [0.0, 0.0]
# setup then sampler for this situation
samples.append(
self._sample_from_polytope(
Expand Down
6 changes: 3 additions & 3 deletions bofire/utils/reduce.py
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ def remove_eliminated_inputs(domain: Domain, transform: AffineTransform) -> Doma
feat: ContinuousInput = ContinuousInput(
**domain.inputs.get_by_key(_features[0]).model_dump(),
)
feat.bounds = (_coefficients[0], _coefficients[0])
feat.bounds = [_coefficients[0], _coefficients[0]]
totally_removed = True
elif len(_features) > 1:
_c = LinearInequalityConstraint(
Expand Down Expand Up @@ -430,6 +430,6 @@ def adjust_boundary(feature: ContinuousInput, coef: float, rhs: float):
boundary = rhs / coef
if coef > 0:
if boundary > feature.lower_bound:
feature.bounds = (boundary, feature.upper_bound)
feature.bounds = [boundary, feature.upper_bound]
elif boundary < feature.upper_bound:
feature.bounds = (feature.lower_bound, boundary)
feature.bounds = [feature.lower_bound, boundary]
11 changes: 5 additions & 6 deletions tests/bofire/data_models/specs/features.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import math
import random
import uuid

Expand Down Expand Up @@ -40,16 +39,16 @@
features.ContinuousInput,
lambda: {
"key": str(uuid.uuid4()),
"bounds": (3, 5.3),
"bounds": [3, 5.3],
"unit": random.choice(["°C", "mg", "mmol/l", None]),
"local_relative_bounds": (math.inf, math.inf),
"local_relative_bounds": None,
"stepsize": None,
},
)

specs.add_invalid(
features.ContinuousInput,
lambda: {"key": "a", "bounds": (5, 3)},
lambda: {"key": "a", "bounds": [5, 3]},
error=ValueError,
message="Sequence is not monotonically increasing.",
)
Expand All @@ -58,11 +57,11 @@
features.ContinuousDescriptorInput,
lambda: {
"key": str(uuid.uuid4()),
"bounds": (3, 5.3),
"bounds": [3, 5.3],
"descriptors": ["d1", "d2"],
"values": [1.0, 2.0],
"unit": random.choice(["°C", "mg", "mmol/l", None]),
"local_relative_bounds": (math.inf, math.inf),
"local_relative_bounds": None,
"stepsize": None,
},
)
Expand Down
4 changes: 2 additions & 2 deletions tests/bofire/data_models/specs/objectives.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
)
specs.add_valid(
objectives.MaximizeObjective,
lambda: {"w": 1.0, "bounds": (0.1, 0.9)},
lambda: {"w": 1.0, "bounds": [0.1, 0.9]},
)
specs.add_valid(
objectives.MaximizeSigmoidObjective,
Expand All @@ -26,7 +26,7 @@
)
specs.add_valid(
objectives.MinimizeObjective,
lambda: {"w": 1.0, "bounds": (0.1, 0.9)},
lambda: {"w": 1.0, "bounds": [0.1, 0.9]},
)

specs.add_valid(
Expand Down
Loading
Loading