Skip to content
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
19 changes: 18 additions & 1 deletion xopt/generators/bayesian/bayesian_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -411,9 +411,12 @@ def generate(self, n_candidates: int):
# dict to track runtimes
timing_results = {}

training_data = self.get_training_data(self.data)
self._validate_contextual_variables_no_nan(training_data)

# update internal model with internal data
start_time = time.perf_counter()
model = self.train_model(self.get_training_data(self.data))
model = self.train_model(training_data)
timing_results["training"] = time.perf_counter() - start_time

# propose candidates given model
Expand Down Expand Up @@ -935,6 +938,20 @@ def get_model_input_bounds(self, data: pd.DataFrame) -> Dict[str, List[float]]:

return variable_bounds

def _validate_contextual_variables_no_nan(self, data: pd.DataFrame):
"""check to make sure that the last row of data does not contain NaN in any of the contextual variable columns"""
last_row = data.iloc[-1]
contextual_with_nan = [
name
for name in self.contextual_variables
if name in data.columns and pd.isna(last_row[name])
]
if contextual_with_nan:
raise ValueError(
"latest row contains NaN in contextual variable columns: "
+ ", ".join(contextual_with_nan)
)

@property
def _candidate_names(self):
"""variable names corresponding to generated candidates"""
Expand Down
17 changes: 17 additions & 0 deletions xopt/tests/generators/bayesian/test_contextual_bo.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,23 @@ def test_contextual_variable_bounds_from_data(self):
assert np.isclose(bounds["x2"][0], 0.3 - padding)
assert np.isclose(bounds["x2"][1], 0.7 + padding)

def test_contextual_variable_nan_in_last_row_raises(self):
generator = UpperConfidenceBoundGenerator(vocs=self.vocs)
data = pd.DataFrame(
{
"x1": np.linspace(0.0, 1.0, 5),
"x2": np.array([0.3, 0.4, 0.5, 0.6, np.nan]),
"y": np.ones(5),
}
)
generator.add_data(data)

with pytest.raises(
ValueError,
match="latest row contains NaN in contextual variable columns",
):
generator.generate(1)

def test_contextual_variable_explicit_domain_overrides_data(self):
vocs = VOCS(
variables={"x1": [0, 1], "x2": ContextualVariable(domain=[0.2, 0.4])},
Expand Down
Loading