Skip to content

Commit eb264f1

Browse files
eonofreymeta-codesync[bot]
authored andcommitted
Fix SearchSpaceAnalysis crash on non-numeric ordered choice parameters (facebook#4991)
Summary: Pull Request resolved: facebook#4991 `search_space_boundary_proportions` assumed all ordered `ChoiceParameter` values are numeric (`int | float`), but some expeirments have ordered string values (somehow?). When this happens, the SearchSpaceBoundary check breaks ([example](https://www.internalfb.com/ax/experiment/p_wyt_directional_v7_ax/experiment)). This diff adds a check that all values are numeric before entering that branch, so non-numeric ordered choice parameters are skipped like unordered ones. Reviewed By: ItsMrLin Differential Revision: D94979372 fbshipit-source-id: a31ffd54aa611c10146ec4805b88dc21a486d572
1 parent a89122d commit eb264f1

File tree

2 files changed

+37
-1
lines changed

2 files changed

+37
-1
lines changed

ax/analysis/healthcheck/search_space_analysis.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,11 @@ def search_space_boundary_proportions(
139139
if isinstance(parameter, RangeParameter):
140140
lower = parameter.lower
141141
upper = parameter.upper
142-
elif isinstance(parameter, ChoiceParameter) and parameter.is_ordered:
142+
elif (
143+
isinstance(parameter, ChoiceParameter)
144+
and parameter.is_ordered
145+
and all(isinstance(v, (int, float)) for v in parameter.values)
146+
):
143147
values = [
144148
assert_is_instance(v, Union[int, float]) for v in parameter.values
145149
]

ax/analysis/healthcheck/tests/test_search_space_analysis.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,3 +178,35 @@ def test_search_space_boundary_proportions(self) -> None:
178178
)
179179
)
180180
)
181+
182+
def test_search_space_boundary_proportions_string_ordered_choice(self) -> None:
183+
"""Test that ordered choice parameters with string values are skipped."""
184+
ss = SearchSpace(
185+
parameters=[
186+
RangeParameter(
187+
name="float_range",
188+
parameter_type=ParameterType.FLOAT,
189+
lower=1.0,
190+
upper=6.0,
191+
),
192+
ChoiceParameter(
193+
name="string_ordered_choice",
194+
parameter_type=ParameterType.STRING,
195+
values=["option_a", "option_b", "option_c"],
196+
is_ordered=True,
197+
),
198+
],
199+
)
200+
201+
parameterizations: list[dict[str, None | bool | float | int | str]] = [
202+
{"float_range": 1.0, "string_ordered_choice": "option_a"},
203+
{"float_range": 3.0, "string_ordered_choice": "option_b"},
204+
]
205+
206+
# Should not raise -- string ordered choice should be skipped
207+
df = search_space_boundary_proportions(
208+
search_space=ss, parameterizations=parameterizations
209+
)
210+
# Only float_range boundaries should be present (lower and upper)
211+
self.assertEqual(len(df), 2)
212+
self.assertTrue(all("float_range" in b for b in df["Boundary"].values))

0 commit comments

Comments
 (0)