Exemplo n.º 1
0
def hypervolume(
    modelbridge: modelbridge_module.array.ArrayModelBridge,
    observation_features: List[ObservationFeatures],
    objective_thresholds: Optional[TRefPoint] = None,
    observation_data: Optional[List[ObservationData]] = None,
    optimization_config: Optional[MultiObjectiveOptimizationConfig] = None,
    use_model_predictions: bool = True,
) -> float:
    """Helper function that computes hypervolume of a given list of outcomes."""
    # Get Pareto front
    observations, f, obj_w, obj_t = get_pareto_frontier_and_transformed_configs(
        modelbridge=modelbridge,
        objective_thresholds=objective_thresholds,
        observation_features=observation_features,
        observation_data=observation_data,
        optimization_config=optimization_config,
        use_model_predictions=use_model_predictions,
    )
    if obj_t is None:
        raise ValueError(
            "Cannot compute hypervolume without having objective thresholds specified."
        )
    # Apply appropriate weights and thresholds
    obj, obj_t = get_weighted_mc_objective_and_objective_thresholds(
        objective_weights=obj_w, objective_thresholds=obj_t)
    f_t = obj(f)
    hv = Hypervolume(ref_point=obj_t)
    return hv.compute(f_t)
Exemplo n.º 2
0
def hypervolume(
    modelbridge: modelbridge_module.array.ArrayModelBridge,
    observation_features: List[ObservationFeatures],
    objective_thresholds: Optional[TRefPoint] = None,
    observation_data: Optional[List[ObservationData]] = None,
    optimization_config: Optional[MultiObjectiveOptimizationConfig] = None,
    use_model_predictions: bool = True,
) -> float:
    """Helper function that computes hypervolume of a given list of outcomes."""
    array_to_tensor = partial(_array_to_tensor, modelbridge=modelbridge)

    # Extract a tensor of outcome means from observation data.
    observations = pareto_frontier(
        modelbridge=modelbridge,
        objective_thresholds=objective_thresholds,
        observation_features=observation_features,
        observation_data=observation_data,
        optimization_config=optimization_config,
        use_model_predictions=use_model_predictions,
    )
    observation_data = [obs.data for obs in observations]
    if not observation_data:
        # The hypervolume of an empty set is always 0.
        return 0
    means, _ = modelbridge.transform_observation_data(observation_data)

    # Extract objective_weights and objective_thresholds
    if optimization_config is None:
        optimization_config = (
            # pyre-ignore[16]: Optional has undefined attr `_optimization_config`
            modelbridge._optimization_config.clone()
            if modelbridge._optimization_config is not None
            else None
        )
    else:
        # pyre-ignore[9]: declared as type `Optional[...]` but used as type `...`
        optimization_config = optimization_config.clone()

    if objective_thresholds is not None:
        optimization_config = optimization_config.clone_with_args(
            objective_thresholds=objective_thresholds
        )

    obj_w = extract_objective_weights(
        objective=optimization_config.objective, outcomes=modelbridge.outcomes
    )
    obj_w = array_to_tensor(obj_w)
    objective_thresholds_arr = extract_objective_thresholds(
        objective_thresholds=optimization_config.objective_thresholds,
        outcomes=modelbridge.outcomes,
    )
    obj_t = array_to_tensor(objective_thresholds_arr)
    obj, obj_t = get_weighted_mc_objective_and_objective_thresholds(
        objective_weights=obj_w, objective_thresholds=obj_t
    )
    means = obj(means)
    hv = Hypervolume(ref_point=obj_t)
    return hv.compute(means)
Exemplo n.º 3
0
    def _hypervolume(
        self,
        objective_thresholds: Optional[TRefPoint] = None,
        observation_features: Optional[List[ObservationFeatures]] = None,
        observation_data: Optional[List[ObservationData]] = None,
        optimization_config: Optional[OptimizationConfig] = None,
    ) -> float:
        # Extract a tensor of outcome means from observation data.
        observation_data = self._pareto_frontier(
            objective_thresholds=objective_thresholds,
            observation_features=observation_features,
            observation_data=observation_data,
            # pyre-fixme[6]: Expected `Optional[MultiObjectiveOptimizationConfig]`
            #  for 4th param but got `Optional[OptimizationConfig]`.
            optimization_config=optimization_config,
        )
        if not observation_data:
            # The hypervolume of an empty set is always 0.
            return 0
        means, _ = self._transform_observation_data(observation_data)

        # Extract objective_weights and objective_thresholds
        if optimization_config is None:
            optimization_config = (
                # pyre-fixme[16]: `Optional` has no attribute `clone`.
                self._optimization_config.clone()
                if self._optimization_config is not None
                else None
            )
        else:
            optimization_config = optimization_config.clone()

        if objective_thresholds is not None:
            optimization_config = optimization_config.clone_with_args(
                objective_thresholds=objective_thresholds
            )

        obj_w = extract_objective_weights(
            objective=optimization_config.objective, outcomes=self.outcomes
        )
        obj_w = self._array_to_tensor(obj_w)  # TODO: can I get rid of these tensors?
        objective_thresholds_arr = extract_objective_thresholds(
            objective_thresholds=optimization_config.objective_thresholds,
            outcomes=self.outcomes,
        )
        obj_t = self._array_to_tensor(
            objective_thresholds_arr
        )  # TODO: can I get rid of these tensors?
        obj, obj_t = get_weighted_mc_objective_and_objective_thresholds(
            objective_weights=obj_w, objective_thresholds=obj_t
        )
        means = obj(means)
        hv = Hypervolume(ref_point=obj_t)
        return hv.compute(means)
Exemplo n.º 4
0
def hypervolume(
    modelbridge: modelbridge_module.array.ArrayModelBridge,
    observation_features: List[ObservationFeatures],
    objective_thresholds: Optional[TRefPoint] = None,
    observation_data: Optional[List[ObservationData]] = None,
    optimization_config: Optional[MultiObjectiveOptimizationConfig] = None,
    selected_metrics: Optional[List[str]] = None,
    use_model_predictions: bool = True,
) -> float:
    """Helper function that computes (feasible) hypervolume.

    Args:
        modelbridge: The modelbridge.
        observation_features: The observation features for the in-sample arms.
        objective_thresholds: The objective thresholds to be used for computing
            the hypervolume. If None, these are extracted from the optimization
            config.
        observation_data: The observed outcomes for the in-sample arms.
        optimization_config: The optimization config specifying the objectives,
            objectives thresholds, and outcome constraints.
        selected_metrics: A list of objective metric names specifying which
            objectives to use in hypervolume computation. By default, all
            objectives are used.
        use_model_predictions: A boolean indicating whether to use model predictions
            for determining the in-sample Pareto frontier instead of the raw observed
            values.

    Returns:
        The (feasible) hypervolume.

    """
    frontier_observations, f, obj_w, obj_t = get_pareto_frontier_and_configs(
        modelbridge=modelbridge,
        observation_features=observation_features,
        observation_data=observation_data,
        objective_thresholds=objective_thresholds,
        optimization_config=optimization_config,
        use_model_predictions=use_model_predictions,
        transform_outcomes_and_configs=False,
    )
    if obj_t is None:
        raise ValueError(
            "Cannot compute hypervolume without having objective thresholds specified."
        )
    oc = _get_multiobjective_optimization_config(
        modelbridge=modelbridge,
        optimization_config=optimization_config,
        objective_thresholds=objective_thresholds,
    )
    # Set to all metrics if unspecified
    if selected_metrics is None:
        selected_metrics = oc.objective.metric_names
    # filter to only include objectives
    else:
        if any(m not in oc.objective.metric_names for m in selected_metrics):
            raise ValueError("All selected metrics must be objectives.")

    # Create a mask indicating selected metrics
    selected_metrics_mask = torch.tensor(
        [metric in selected_metrics for metric in modelbridge.outcomes],
        dtype=torch.bool,
        device=f.device,
    )
    # Apply appropriate weights and thresholds
    obj, obj_t = get_weighted_mc_objective_and_objective_thresholds(
        objective_weights=obj_w, objective_thresholds=not_none(obj_t))
    f_t = obj(f)
    # pyre-ignore [16]
    obj_mask = obj_w.nonzero().view(-1)
    selected_metrics_mask = selected_metrics_mask[obj_mask]
    f_t = f_t[:, selected_metrics_mask]
    obj_t = obj_t[selected_metrics_mask]
    bd = DominatedPartitioning(ref_point=obj_t, Y=f_t)
    return bd.compute_hypervolume().item()