def metric_from_sqa( self, metric_sqa: SQAMetric ) -> Union[Metric, Objective, OutcomeConstraint]: """Convert SQLAlchemy Metric to Ax Metric, Objective, or OutcomeConstraint.""" metric = self.metric_from_sqa_util(metric_sqa) if metric_sqa.intent == MetricIntent.TRACKING: return metric elif metric_sqa.intent == MetricIntent.OBJECTIVE: if metric_sqa.minimize is None: raise SQADecodeError( # pragma: no cover "Cannot decode SQAMetric to Objective because minimize is None." ) if metric_sqa.scalarized_objective_weight is not None: raise SQADecodeError( # pragma: no cover "The metric corresponding to regular objective does not \ have weight attribute") return Objective(metric=metric, minimize=metric_sqa.minimize) elif (metric_sqa.intent == MetricIntent.MULTI_OBJECTIVE ): # metric_sqa is a parent whose children are individual # metrics in MultiObjective try: metrics_sqa_children = metric_sqa.scalarized_objective_children_metrics except DetachedInstanceError: metrics_sqa_children = _get_scalarized_objective_children_metrics( metric_id=metric_sqa.id, decoder=self) if metrics_sqa_children is None: raise SQADecodeError( # pragma: no cover "Cannot decode SQAMetric to MultiObjective \ because the parent metric has no children metrics.") # Extracting metric and weight for each child objectives = [ Objective( metric=self.metric_from_sqa_util(metric_sqa), minimize=metric_sqa.minimize, ) for metric_sqa in metrics_sqa_children ] multi_objective = MultiObjective(objectives=objectives) multi_objective.db_id = metric_sqa.id return multi_objective elif (metric_sqa.intent == MetricIntent.SCALARIZED_OBJECTIVE ): # metric_sqa is a parent whose children are individual # metrics in Scalarized Objective if metric_sqa.minimize is None: raise SQADecodeError( # pragma: no cover "Cannot decode SQAMetric to Scalarized Objective \ because minimize is None.") try: metrics_sqa_children = metric_sqa.scalarized_objective_children_metrics except DetachedInstanceError: metrics_sqa_children = _get_scalarized_objective_children_metrics( metric_id=metric_sqa.id, decoder=self) if metrics_sqa_children is None: raise SQADecodeError( # pragma: no cover "Cannot decode SQAMetric to Scalarized Objective \ because the parent metric has no children metrics.") # Extracting metric and weight for each child metrics, weights = zip(*[( self.metric_from_sqa_util(child), child.scalarized_objective_weight, ) for child in metrics_sqa_children]) scalarized_objective = ScalarizedObjective( metrics=list(metrics), weights=list(weights), minimize=not_none(metric_sqa.minimize), ) scalarized_objective.db_id = metric_sqa.id return scalarized_objective elif metric_sqa.intent == MetricIntent.OUTCOME_CONSTRAINT: if (metric_sqa.bound is None or metric_sqa.op is None or metric_sqa.relative is None): raise SQADecodeError( # pragma: no cover "Cannot decode SQAMetric to OutcomeConstraint because " "bound, op, or relative is None.") return OutcomeConstraint( metric=metric, bound=metric_sqa.bound, op=metric_sqa.op, relative=metric_sqa.relative, ) elif metric_sqa.intent == MetricIntent.SCALARIZED_OUTCOME_CONSTRAINT: if (metric_sqa.bound is None or metric_sqa.op is None or metric_sqa.relative is None): raise SQADecodeError( # pragma: no cover "Cannot decode SQAMetric to Scalarized OutcomeConstraint because " "bound, op, or relative is None.") try: metrics_sqa_children = ( metric_sqa.scalarized_outcome_constraint_children_metrics) except DetachedInstanceError: metrics_sqa_children = ( _get_scalarized_outcome_constraint_children_metrics( metric_id=metric_sqa.id, decoder=self)) if metrics_sqa_children is None: raise SQADecodeError( # pragma: no cover "Cannot decode SQAMetric to Scalarized OutcomeConstraint \ because the parent metric has no children metrics.") # Extracting metric and weight for each child metrics, weights = zip(*[( self.metric_from_sqa_util(child), child.scalarized_outcome_constraint_weight, ) for child in metrics_sqa_children]) scalarized_outcome_constraint = ScalarizedOutcomeConstraint( metrics=list(metrics), weights=list(weights), bound=not_none(metric_sqa.bound), op=not_none(metric_sqa.op), relative=not_none(metric_sqa.relative), ) scalarized_outcome_constraint.db_id = metric_sqa.id return scalarized_outcome_constraint elif metric_sqa.intent == MetricIntent.OBJECTIVE_THRESHOLD: if metric_sqa.bound is None or metric_sqa.relative is None: raise SQADecodeError( # pragma: no cover "Cannot decode SQAMetric to ObjectiveThreshold because " "bound, op, or relative is None.") ot = ObjectiveThreshold( metric=metric, bound=metric_sqa.bound, relative=metric_sqa.relative, op=metric_sqa.op, ) # ObjectiveThreshold constructor clones the passed-in metric, which means # the db id gets lost and so we need to reset it ot.metric._db_id = metric.db_id return ot else: raise SQADecodeError( f"Cannot decode SQAMetric because {metric_sqa.intent} " f"is an invalid intent.")
def metric_from_sqa( self, metric_sqa: SQAMetric ) -> Union[Metric, Objective, OutcomeConstraint]: """Convert SQLAlchemy Metric to Ax Metric, Objective, or OutcomeConstraint.""" metric = self.metric_from_sqa_util(metric_sqa) if metric_sqa.intent == MetricIntent.TRACKING: return metric elif metric_sqa.intent == MetricIntent.OBJECTIVE: if metric_sqa.minimize is None: raise SQADecodeError( # pragma: no cover "Cannot decode SQAMetric to Objective because minimize is None." ) if metric_sqa.scalarized_objective_weight is not None: raise SQADecodeError( # pragma: no cover "The metric corresponding to regular objective does not \ have weight attribute") return Objective(metric=metric, minimize=metric_sqa.minimize) elif (metric_sqa.intent == MetricIntent.MULTI_OBJECTIVE ): # metric_sqa is a parent whose children are individual # metrics in MultiObjective if metric_sqa.minimize is None: raise SQADecodeError( # pragma: no cover "Cannot decode SQAMetric to MultiObjective \ because minimize is None.") metrics_sqa_children = metric_sqa.scalarized_objective_children_metrics if metrics_sqa_children is None: raise SQADecodeError( # pragma: no cover "Cannot decode SQAMetric to MultiObjective \ because the parent metric has no children metrics.") # Extracting metric and weight for each child metrics = [ self.metric_from_sqa_util(child) for child in metrics_sqa_children ] multi_objective = MultiObjective( metrics=list(metrics), # pyre-fixme[6]: Expected `bool` for 2nd param but got `Optional[bool]`. minimize=metric_sqa.minimize, ) multi_objective.db_id = metric_sqa.id return multi_objective elif (metric_sqa.intent == MetricIntent.SCALARIZED_OBJECTIVE ): # metric_sqa is a parent whose children are individual # metrics in Scalarized Objective if metric_sqa.minimize is None: raise SQADecodeError( # pragma: no cover "Cannot decode SQAMetric to Scalarized Objective \ because minimize is None.") metrics_sqa_children = metric_sqa.scalarized_objective_children_metrics if metrics_sqa_children is None: raise SQADecodeError( # pragma: no cover "Cannot decode SQAMetric to Scalarized Objective \ because the parent metric has no children metrics.") # Extracting metric and weight for each child metrics, weights = zip(*[( self.metric_from_sqa_util(child), child.scalarized_objective_weight, ) for child in metrics_sqa_children]) scalarized_objective = ScalarizedObjective( metrics=list(metrics), weights=list(weights), # pyre-fixme[6]: Expected `bool` for 3nd param but got `Optional[bool]`. minimize=metric_sqa.minimize, ) scalarized_objective.db_id = metric_sqa.id return scalarized_objective elif metric_sqa.intent == MetricIntent.OUTCOME_CONSTRAINT: if (metric_sqa.bound is None or metric_sqa.op is None or metric_sqa.relative is None): raise SQADecodeError( # pragma: no cover "Cannot decode SQAMetric to OutcomeConstraint because " "bound, op, or relative is None.") return OutcomeConstraint( metric=metric, # pyre-fixme[6]: Expected `float` for 2nd param but got # `Optional[float]`. bound=metric_sqa.bound, op=metric_sqa.op, relative=metric_sqa.relative, ) elif metric_sqa.intent == MetricIntent.SCALARIZED_OUTCOME_CONSTRAINT: if (metric_sqa.bound is None or metric_sqa.op is None or metric_sqa.relative is None): raise SQADecodeError( # pragma: no cover "Cannot decode SQAMetric to Scalarized OutcomeConstraint because " "bound, op, or relative is None.") metrics_sqa_children = ( metric_sqa.scalarized_outcome_constraint_children_metrics) if metrics_sqa_children is None: raise SQADecodeError( # pragma: no cover "Cannot decode SQAMetric to Scalarized OutcomeConstraint \ because the parent metric has no children metrics.") # Extracting metric and weight for each child metrics, weights = zip(*[( self.metric_from_sqa_util(child), child.scalarized_outcome_constraint_weight, ) for child in metrics_sqa_children]) scalarized_outcome_constraint = ScalarizedOutcomeConstraint( metrics=list(metrics), weights=list(weights), # pyre-fixme[6]: Expected `float` for 2nd param but got # `Optional[float]`. bound=metric_sqa.bound, op=metric_sqa.op, relative=metric_sqa.relative, ) scalarized_outcome_constraint.db_id = metric_sqa.id return scalarized_outcome_constraint elif metric_sqa.intent == MetricIntent.OBJECTIVE_THRESHOLD: if metric_sqa.bound is None or metric_sqa.relative is None: raise SQADecodeError( # pragma: no cover "Cannot decode SQAMetric to ObjectiveThreshold because " "bound, op, or relative is None.") return ObjectiveThreshold( metric=metric, # pyre-fixme[6]: Expected `float` for 2nd param but got # `Optional[float]`. bound=metric_sqa.bound, relative=metric_sqa.relative, op=metric_sqa.op, ) else: raise SQADecodeError( f"Cannot decode SQAMetric because {metric_sqa.intent} " f"is an invalid intent.")