|
8 | 8 | from collections.abc import Sequence |
9 | 9 |
|
10 | 10 | from ax.core.map_metric import MapMetric |
11 | | - |
12 | 11 | from ax.core.objective import MultiObjective, Objective, ScalarizedObjective |
13 | 12 | from ax.core.optimization_config import ( |
14 | 13 | MultiObjectiveOptimizationConfig, |
|
20 | 19 | OutcomeConstraint, |
21 | 20 | ScalarizedOutcomeConstraint, |
22 | 21 | ) |
23 | | -from ax.core.parameter_constraint import ParameterConstraint |
24 | 22 | from ax.exceptions.core import UserInputError |
25 | 23 | from ax.utils.common.string_utils import sanitize_name, unsanitize_name |
| 24 | +from ax.utils.common.sympy import extract_coefficient_dict_from_inequality |
26 | 25 | from pyre_extensions import assert_is_instance, none_throws |
27 | 26 | from sympy.core.add import Add |
28 | 27 | from sympy.core.expr import Expr |
29 | 28 | from sympy.core.mul import Mul |
30 | | -from sympy.core.relational import GreaterThan, LessThan |
31 | 29 | from sympy.core.symbol import Symbol |
32 | 30 | from sympy.core.sympify import sympify |
33 | 31 |
|
@@ -95,35 +93,6 @@ def optimization_config_from_string( |
95 | 93 | ) |
96 | 94 |
|
97 | 95 |
|
98 | | -def parse_parameter_constraint(constraint_str: str) -> ParameterConstraint: |
99 | | - """ |
100 | | - Parse a parameter constraint string into a ParameterConstraint object using SymPy. |
101 | | - Currently only supports linear constraints of the form "a * x + b * y >= k" or |
102 | | - "a * x + b * y <= k". |
103 | | - """ |
104 | | - coefficient_dict = _extract_coefficient_dict_from_inequality( |
105 | | - inequality_str=constraint_str |
106 | | - ) |
107 | | - |
108 | | - # Iterate through the coefficients to extract the parameter names and weights and |
109 | | - # the bound |
110 | | - constraint_dict = {} |
111 | | - bound = 0 |
112 | | - for term, coefficient in coefficient_dict.items(): |
113 | | - if term.is_symbol: |
114 | | - constraint_dict[unsanitize_name(term.name)] = coefficient |
115 | | - elif term.is_number: |
116 | | - # Invert because we are "moving" the bound to the right hand side |
117 | | - bound = -1 * coefficient |
118 | | - else: |
119 | | - raise UserInputError( |
120 | | - "Only linear inequality parameter constraints are supported, found " |
121 | | - f"{constraint_str}" |
122 | | - ) |
123 | | - |
124 | | - return ParameterConstraint(constraint_dict=constraint_dict, bound=bound) |
125 | | - |
126 | | - |
127 | 96 | def parse_objective(objective_str: str) -> Objective: |
128 | 97 | """ |
129 | 98 | Parse an objective string into an Objective object using SymPy. |
@@ -154,7 +123,7 @@ def parse_outcome_constraint(constraint_str: str) -> OutcomeConstraint: |
154 | 123 | multiply your bound by "baseline". For example "qps >= 0.95 * baseline" will |
155 | 124 | constrain such that the QPS is at least 95% of the baseline arm's QPS. |
156 | 125 | """ |
157 | | - coefficient_dict = _extract_coefficient_dict_from_inequality( |
| 126 | + coefficient_dict = extract_coefficient_dict_from_inequality( |
158 | 127 | inequality_str=constraint_str |
159 | 128 | ) |
160 | 129 |
|
@@ -248,31 +217,3 @@ def _create_single_objective(expression: Expr) -> Objective: |
248 | 217 | ) |
249 | 218 |
|
250 | 219 | raise UserInputError(f"Only linear objectives are supported, found {expression}.") |
251 | | - |
252 | | - |
253 | | -def _extract_coefficient_dict_from_inequality( |
254 | | - inequality_str: str, |
255 | | -) -> dict[Symbol, float]: |
256 | | - """ |
257 | | - Use SymPy to parse a string into an inequality, invert if necessary to enforce a |
258 | | - less-than relationship, move all terms to the left side, and return the |
259 | | - coefficients as a dictionary. This is useful for parsing parameter and outcome |
260 | | - constraints. |
261 | | - """ |
262 | | - # Parse the constraint string into a SymPy inequality |
263 | | - inequality = sympify(sanitize_name(inequality_str)) |
264 | | - |
265 | | - # Check the SymPy object is a valid inequality |
266 | | - if not isinstance(inequality, GreaterThan | LessThan): |
267 | | - raise UserInputError(f"Expected an inequality, found {inequality_str}") |
268 | | - |
269 | | - # Move all terms to the left side of the inequality and invert if necessary to |
270 | | - # enforce a less-than relationship |
271 | | - if isinstance(inequality, LessThan): |
272 | | - expression = inequality.lhs - inequality.rhs |
273 | | - else: |
274 | | - expression = inequality.rhs - inequality.lhs |
275 | | - |
276 | | - return { |
277 | | - key: float(value) for key, value in expression.as_coefficients_dict().items() |
278 | | - } |
0 commit comments