(
    train_x: "torch.Tensor",
    train_obj: "torch.Tensor",
    train_con: Optional["torch.Tensor"],
    bounds: "torch.Tensor",
)
return candidates
Quasi MC-based batch Expected Hypervolume Improvement (qEHVI).

    The default value of ``candidates_func`` in :class:`~optuna.integration.BoTorchSampler`
    with multi-objective optimization when the number of objectives is three or less.

    .. seealso::
        :func:`~optuna.integration.botorch.qei_candidates_func` for argument and return value
        descriptions.
Quasi MC-based batch Expected Hypervolume Improvement (qEHVI).
Quasi MC - based batch Expected Hypervolume Improvement ( qEHVI ) .
def qehvi_candidates_func(
    train_x: "torch.Tensor",
    train_obj: "torch.Tensor",
    train_con: Optional["torch.Tensor"],
    bounds: "torch.Tensor",
) -> "torch.Tensor":
    """Quasi MC-based batch Expected Hypervolume Improvement (qEHVI).

    The default value of ``candidates_func`` in :class:`~optuna.integration.BoTorchSampler`
    with multi-objective optimization when the number of objectives is three or less.

    .. seealso::
        :func:`~optuna.integration.botorch.qei_candidates_func` for argument and return value
        descriptions.
    """

    n_objectives = train_obj.size(-1)

    if train_con is not None:
        train_y = torch.cat([train_obj, train_con], dim=-1)

        is_feas = (train_con <= 0).all(dim=-1)
        train_obj_feas = train_obj[is_feas]

        constraints = []
        n_constraints = train_con.size(1)

        for i in range(n_constraints):
            constraints.append(lambda Z, i=i: Z[..., -n_constraints + i])
        additional_qehvi_kwargs = {
            "objective": IdentityMCMultiOutputObjective(outcomes=list(range(n_objectives))),
            "constraints": constraints,
        }
    else:
        train_y = train_obj

        train_obj_feas = train_obj

        additional_qehvi_kwargs = {}

    train_x = normalize(train_x, bounds=bounds)

    model = SingleTaskGP(train_x, train_y, outcome_transform=Standardize(m=train_y.shape[-1]))
    mll = ExactMarginalLogLikelihood(model.likelihood, model)
    fit_gpytorch_model(mll)

    # Approximate box decomposition similar to Ax when the number of objectives is large.
    # https://github.com/facebook/Ax/blob/master/ax/models/torch/botorch_moo_defaults
    if n_objectives > 2:
        alpha = 10 ** (-8 + n_objectives)
    else:
        alpha = 0.0

    ref_point = train_obj.min(dim=0).values - 1e-8

    partitioning = NondominatedPartitioning(ref_point=ref_point, Y=train_obj_feas, alpha=alpha)

    ref_point_list = ref_point.tolist()

    acqf = qExpectedHypervolumeImprovement(
        model=model,
        ref_point=ref_point_list,
        partitioning=partitioning,
        sampler=SobolQMCNormalSampler(num_samples=256),
        **additional_qehvi_kwargs,
    )

    standard_bounds = torch.zeros_like(bounds)
    standard_bounds[1] = 1

    candidates, _ = optimize_acqf(
        acq_function=acqf,
        bounds=standard_bounds,
        q=1,
        num_restarts=20,
        raw_samples=1024,
        options={"batch_limit": 5, "maxiter": 200, "nonnegative": True},
        sequential=True,
    )

    candidates = unnormalize(candidates.detach(), bounds=bounds)

    return candidates
def qehvi_candidates_func ( train_x : "torch.Tensor" , train_obj : "torch.Tensor" , train_con : Optional [ "torch.Tensor" ] , bounds : "torch.Tensor" , ) -> "torch.Tensor" : n_objectives = train_obj . size ( - 1 ) if train_con is not None : train_y = torch . cat ( [ train_obj , train_con ] , dim = - 1 ) is_feas = ( train_con <= 0 ) . all ( dim = - 1 ) train_obj_feas = train_obj [ is_feas ] constraints = [ ] n_constraints = train_con . size ( 1 ) for i in range ( n_constraints ) : constraints . append ( lambda Z , i = i : Z [ ... , - n_constraints + i ] ) additional_qehvi_kwargs = { "objective" : IdentityMCMultiOutputObjective ( outcomes = list ( range ( n_objectives ) ) ) , "constraints" : constraints , } else : train_y = train_obj train_obj_feas = train_obj additional_qehvi_kwargs = { } train_x = normalize ( train_x , bounds = bounds ) model = SingleTaskGP ( train_x , train_y , outcome_transform = Standardize ( m = train_y . shape [ - 1 ] ) ) mll = ExactMarginalLogLikelihood ( model . likelihood , model ) fit_gpytorch_model ( mll ) # Approximate box decomposition similar to Ax when the number of objectives is large. # https://github.com/facebook/Ax/blob/master/ax/models/torch/botorch_moo_defaults if n_objectives > 2 : alpha = 10 ** ( - 8 + n_objectives ) else : alpha = 0.0 ref_point = train_obj . min ( dim = 0 ) . values - 1e-8 partitioning = NondominatedPartitioning ( ref_point = ref_point , Y = train_obj_feas , alpha = alpha ) ref_point_list = ref_point . tolist ( ) acqf = qExpectedHypervolumeImprovement ( model = model , ref_point = ref_point_list , partitioning = partitioning , sampler = SobolQMCNormalSampler ( num_samples = 256 ) , * * additional_qehvi_kwargs , ) standard_bounds = torch . zeros_like ( bounds ) standard_bounds [ 1 ] = 1 candidates , _ = optimize_acqf ( acq_function = acqf , bounds = standard_bounds , q = 1 , num_restarts = 20 , raw_samples = 1024 , options = { "batch_limit" : 5 , "maxiter" : 200 , "nonnegative" : True } , sequential = True , ) candidates = unnormalize ( candidates . detach ( ) , bounds = bounds ) return candidates