Skip to content

Commit c2bea5c

Browse files
metactcfacebook-github-bot
authored andcommitted
Enable json serialization of ScalarizedOutcomeConstraint (facebook#5025)
Summary: Adds JSON serialization/deserialization support for ScalarizedOutcomeConstraint in Ax's JSON storage. = Background ScalarizedOutcomeConstraint differs from OutcomeConstraint in that it holds a list of metrics and weights instead of a single metric. Accessing .metric on a ScalarizedOutcomeConstraint raises NotImplementedError, so the existing outcome_constraint_to_dict encoder cannot be reused. = Solution This diff implements a dedicated encoder (scalarized_outcome_constraint_to_dict) following the same pattern as ScalarizedObjective. = Motivation This issue was discovered when serializing an experiment loaded from the Ax DB via object_to_json. The experiment's historical GeneratorRun objects contained ScalarizedOutcomeConstraint instances (set by Bayesian optimization), which caused serialization to fail. **Note:** The SQA (database) store already handles this type; the JSON store was the only gap. Reviewed By: bletham Differential Revision: D96486632
1 parent 987833b commit c2bea5c

File tree

3 files changed

+25
-2
lines changed

3 files changed

+25
-2
lines changed

ax/storage/json_store/encoders.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
OptimizationConfig,
2727
PreferenceOptimizationConfig,
2828
)
29-
from ax.core.outcome_constraint import OutcomeConstraint
29+
from ax.core.outcome_constraint import OutcomeConstraint, ScalarizedOutcomeConstraint
3030
from ax.core.parameter import (
3131
ChoiceParameter,
3232
DerivedParameter,
@@ -362,6 +362,20 @@ def outcome_constraint_to_dict(outcome_constraint: OutcomeConstraint) -> dict[st
362362
}
363363

364364

365+
def scalarized_outcome_constraint_to_dict(
366+
outcome_constraint: ScalarizedOutcomeConstraint,
367+
) -> dict[str, Any]:
368+
"""Convert Ax scalarized outcome constraint to a dictionary."""
369+
return {
370+
"__type": outcome_constraint.__class__.__name__,
371+
"metrics": outcome_constraint.metrics,
372+
"weights": outcome_constraint.weights,
373+
"op": outcome_constraint.op,
374+
"bound": outcome_constraint.bound,
375+
"relative": outcome_constraint.relative,
376+
}
377+
378+
365379
def optimization_config_to_dict(
366380
optimization_config: OptimizationConfig,
367381
) -> dict[str, Any]:

ax/storage/json_store/registry.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,11 @@
4747
OptimizationConfig,
4848
PreferenceOptimizationConfig,
4949
)
50-
from ax.core.outcome_constraint import ObjectiveThreshold, OutcomeConstraint
50+
from ax.core.outcome_constraint import (
51+
ObjectiveThreshold,
52+
OutcomeConstraint,
53+
ScalarizedOutcomeConstraint,
54+
)
5155
from ax.core.parameter import (
5256
ChoiceParameter,
5357
DerivedParameter,
@@ -159,6 +163,7 @@
159163
range_parameter_to_dict,
160164
runner_to_dict,
161165
scalarized_objective_to_dict,
166+
scalarized_outcome_constraint_to_dict,
162167
search_space_to_dict,
163168
surrogate_to_dict,
164169
threshold_early_stopping_strategy_to_dict,
@@ -255,6 +260,7 @@
255260
OptimizationConfig: optimization_config_to_dict,
256261
OrEarlyStoppingStrategy: logical_early_stopping_strategy_to_dict,
257262
OutcomeConstraint: outcome_constraint_to_dict,
263+
ScalarizedOutcomeConstraint: scalarized_outcome_constraint_to_dict,
258264
ParameterConstraint: parameter_constraint_to_dict,
259265
pathlib.Path: pathlib_to_dict,
260266
pathlib.PurePath: pathlib_to_dict,
@@ -410,6 +416,7 @@
410416
"ReductionCriterion": ReductionCriterion,
411417
"Round": Round,
412418
"ScalarizedObjective": ScalarizedObjective,
419+
"ScalarizedOutcomeConstraint": ScalarizedOutcomeConstraint,
413420
"SchedulerOptions": OrchestratorOptions, # DEPRECATED; backward compatibility
414421
"SearchSpace": SearchSpace,
415422
"SimTrial": SimTrial,

ax/storage/json_store/tests/test_json_store.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@
153153
get_percentile_early_stopping_strategy_with_non_objective_metric_signature,
154154
get_range_parameter,
155155
get_scalarized_objective,
156+
get_scalarized_outcome_constraint,
156157
get_search_space,
157158
get_sorted_choice_parameter,
158159
get_sum_constraint1,
@@ -391,6 +392,7 @@
391392
("ParameterConstraint", get_parameter_constraint),
392393
("RangeParameter", get_range_parameter),
393394
("ScalarizedObjective", get_scalarized_objective),
395+
("ScalarizedOutcomeConstraint", get_scalarized_outcome_constraint),
394396
("OrchestratorOptions", get_default_orchestrator_options),
395397
("OrchestratorOptions", get_orchestrator_options_batch_trial),
396398
("SearchSpace", get_search_space),

0 commit comments

Comments
 (0)