class_docstr: The acquisition function for the multi-objective joint entropy search, where
  the batches `q > 1` are supported through the lower bound formulation.
  
  This acquisition function computes the mutual information between the observation
  at a candidate point `X` and the Pareto optimal input-output pairs.
  
  See [Tu2022]_ for a discussion on the estimation procedure.
  
  NOTES:
  (i) The estimated acquisition value could be negative.
  
  (ii) The lower bound batch acquisition function might not be monotone in the
  sense that adding more elements to the batch does not necessarily increase the
  acquisition value. Specifically, the acquisition value can become smaller when
  more inputs are added.
class_docstr_tok: ["The","acquisition","function","for","the","multi-objective","joint","entropy","search",",","where","the","batches","`","q",">","1","`","are","supported","through","the","lower","bound","formulation",".","This","acquisition","function","computes","the","mutual","information","between","the","observation","at","a","candidate","point","`","X","`","and","the","Pareto","optimal","input-output","pairs",".","See","[","Tu2022","]","_","for","a","discussion","on","the","estimation","procedure",".","NOTES",":","(","i",")","The","estimated","acquisition","value","could","be","negative",".","(","ii",")","The","lower","bound","batch","acquisition","function","might","not","be","monotone","in","the","sense","that","adding","more","elements","to","the","batch","does","not","necessarily","increase","the","acquisition","value",".","Specifically",",","the","acquisition","value","can","become","smaller","when","more","inputs","are","added","."]
docstr: Lower bound multi-objective joint entropy search acquisition function.
  
  Args:
      model: A fitted batch model with 'M' number of outputs.
      pareto_sets: A `num_pareto_samples x num_pareto_points x d`-dim Tensor
          containing the sampled Pareto optimal sets of inputs.
      pareto_fronts: A `num_pareto_samples x num_pareto_points x M`-dim Tensor
          containing the sampled Pareto optimal sets of outputs.
      hypercell_bounds:  A `num_pareto_samples x 2 x J x M`-dim Tensor
          containing the hyper-rectangle bounds for integration. In the
          unconstrained case, this gives the partition of the dominated space.
          In the constrained case, this gives the partition of the feasible
          dominated space union the infeasible space.
      X_pending: A `m x d`-dim Tensor of `m` design points that have been
          submitted for function evaluation, but have not yet been evaluated.
      estimation_type: A string to determine which entropy estimate is
          computed: "0", "LB", "LB2", or "MC".
      num_samples: The number of Monte Carlo samples used for the Monte Carlo
          estimate.
docstr_tok: ["Lower","bound","multi-objective","joint","entropy","search","acquisition","function",".","Args",":","model",":","A","fitted","batch","model","with","'M","'","number","of","outputs",".","pareto_sets",":","A","`","num_pareto_samples","x","num_pareto_points","x","d","`","-dim","Tensor","containing","the","sampled","Pareto","optimal","sets","of","inputs",".","pareto_fronts",":","A","`","num_pareto_samples","x","num_pareto_points","x","M","`","-dim","Tensor","containing","the","sampled","Pareto","optimal","sets","of","outputs",".","hypercell_bounds",":","A","`","num_pareto_samples","x","2","x","J","x","M","`","-dim","Tensor","containing","the","hyper-rectangle","bounds","for","integration",".","In","the","unconstrained","case",",","this","gives","the","partition","of","the","dominated","space",".","In","the","constrained","case",",","this","gives","the","partition","of","the","feasible","dominated","space","union","the","infeasible","space",".","X_pending",":","A","`","m","x","d","`","-dim","Tensor","of","`","m","`","design","points","that","have","been","submitted","for","function","evaluation",",","but","have","not","yet","been","evaluated",".","estimation_type",":","A","string","to","determine","which","entropy","estimate","is","computed",":","``","0","''",",","``","LB","''",",","``","LB2","''",",","or","``","MC","''",".","num_samples",":","The","number","of","Monte","Carlo","samples","used","for","the","Monte","Carlo","estimate","."]
code: def __init__(
      self,
      model: Model,
      pareto_sets: Tensor,
      pareto_fronts: Tensor,
      hypercell_bounds: Tensor,
      X_pending: Optional[Tensor] = None,
      estimation_type: str = "LB",
      num_samples: int = 64,
      **kwargs: Any,
  ) -> None:
      r"""Lower bound multi-objective joint entropy search acquisition function.
  
      Args:
          model: A fitted batch model with 'M' number of outputs.
          pareto_sets: A `num_pareto_samples x num_pareto_points x d`-dim Tensor
              containing the sampled Pareto optimal sets of inputs.
          pareto_fronts: A `num_pareto_samples x num_pareto_points x M`-dim Tensor
              containing the sampled Pareto optimal sets of outputs.
          hypercell_bounds:  A `num_pareto_samples x 2 x J x M`-dim Tensor
              containing the hyper-rectangle bounds for integration. In the
              unconstrained case, this gives the partition of the dominated space.
              In the constrained case, this gives the partition of the feasible
              dominated space union the infeasible space.
          X_pending: A `m x d`-dim Tensor of `m` design points that have been
              submitted for function evaluation, but have not yet been evaluated.
          estimation_type: A string to determine which entropy estimate is
              computed: "0", "LB", "LB2", or "MC".
          num_samples: The number of Monte Carlo samples used for the Monte Carlo
              estimate.
      """
      super().__init__(
          model=model,
          pareto_sets=pareto_sets,
          pareto_fronts=pareto_fronts,
          hypercell_bounds=hypercell_bounds,
          X_pending=X_pending,
          estimation_type=estimation_type,
          num_samples=num_samples,
      )
  
      # Condition the model on the sampled pareto optimal points.
      # TODO: Apparently, we need to make a call to the posterior otherwise
      #  we run into a gpytorch runtime error:
      #  "Fantasy observations can only be added after making predictions with a
      #  model so that all test independent caches exist."
  
      with fantasize_flag():
          with settings.propagate_grads(False):
              _ = self.initial_model.posterior(
                  self.pareto_sets, observation_noise=False
              )
          # Condition with observation noise.
          self.conditional_model = (
              self.initial_model.condition_on_observations(
                  X=self.initial_model.transform_inputs(
                      self.pareto_sets
                  ),
                  Y=self.pareto_fronts,
              )
          )
  
imports: from __future__ import annotations
  from abc import abstractmethod
  from math import pi
  from typing import Any, Optional, Tuple, Union
  import torch
  from botorch import settings
  from botorch.acquisition.acquisition import AcquisitionFunction, MCSamplerMixin
  from botorch.exceptions.errors import UnsupportedError
  from botorch.models.model import Model
  from botorch.models.model_list_gp_regression import ModelListGP
  from botorch.models.utils import fantasize
  from botorch.posteriors.gpytorch import GPyTorchPosterior
  from botorch.sampling.normal import SobolQMCNormalSampler
  from botorch.utils.transforms import concatenate_pending_points, t_batch_mode_transform
  from torch import Tensor
  from torch.distributions import Normal
label_desc: Use image node_id 1 to create a new qLowerBoundMultiObjectiveJointEntropySearch object from inherited base classes: LowerBoundMultiObjectiveEntropySearch with example: obj = qLowerBoundMultiObjectiveJointEntropySearch(model, pareto_sets, pareto_fronts, hypercell_bounds, X_pending, estimation_type, num_samples)