class_docstr: Penalized MC objective.
  
  Allows to construct a penalized MC-objective by adding a penalty term to
  the original objective.
  
      mc_acq(X) = objective(X) + penalty_objective(X)
  
  Note: PenalizedMCObjective allows adding penalty at the MCObjective level,
  different from the AcquisitionFunction level in PenalizedAcquisitionFunction.
  
  Example:
      >>> regularization_parameter = 0.01
      >>> init_point = torch.zeros(3) # assume data dim is 3
      >>> objective = lambda Y, X: torch.sqrt(Y).sum(dim=-1)
      >>> l1_penalty_objective = L1PenaltyObjective(init_point=init_point)
      >>> l1_penalized_objective = PenalizedMCObjective(
              objective, l1_penalty_objective, regularization_parameter
          )
      >>> samples = sampler(posterior)
              objective, l1_penalty_objective, regularization_parameter
docstr: Evaluate the penalized objective on the samples.
  
  Args:
      samples: A `sample_shape x batch_shape x q x m`-dim Tensors of
          samples from a model posterior.
      X: A `batch_shape x q x d`-dim tensor of inputs. Relevant only if
          the objective depends on the inputs explicitly.
  
  Returns:
      A `sample_shape x batch_shape x q`-dim Tensor of objective values
      with penalty added for each point.
docstr_tok: ["Evaluate","the","penalized","objective","on","the","samples",".","Args",":","samples",":","A","`","sample_shape","x","batch_shape","x","q","x","m","`","-dim","Tensors","of","samples","from","a","model","posterior",".","X",":","A","`","batch_shape","x","q","x","d","`","-dim","tensor","of","inputs",".","Relevant","only","if","the","objective","depends","on","the","inputs","explicitly",".","Returns",":","A","`","sample_shape","x","batch_shape","x","q","`","-dim","Tensor","of","objective","values","with","penalty","added","for","each","point","."]
code: def forward(
      self, samples: Tensor, X: Optional[Tensor] = None
  ) -> Tensor:
      r"""Evaluate the penalized objective on the samples.
  
      Args:
          samples: A `sample_shape x batch_shape x q x m`-dim Tensors of
              samples from a model posterior.
          X: A `batch_shape x q x d`-dim tensor of inputs. Relevant only if
              the objective depends on the inputs explicitly.
  
      Returns:
          A `sample_shape x batch_shape x q`-dim Tensor of objective values
          with penalty added for each point.
      """
      obj = super().forward(samples=samples, X=X)
      penalty_obj = self.penalty_objective(X)
      # when fully bayesian model is used, we pass unmarginalize_dim to match the
      # shape between obj `sample_shape x batch-shape x mcmc_samples x q` and
      # penalty_obj `1 x batch-shape x q`
      if self.expand_dim is not None:
          # reshape penalty_obj to match the dim
          penalty_obj = penalty_obj.unsqueeze(self.expand_dim)
      # this happens when samples is a `q x m`-dim tensor and X is a `q x d`-dim
      # tensor; obj returned from GenericMCObjective is a `q`-dim tensor and
      # penalty_obj is a `1 x q`-dim tensor.
      if obj.ndim == 1:
          assert penalty_obj.shape == torch.Size([1, samples.shape[-2]])
          penalty_obj = penalty_obj.squeeze(dim=0)
      return obj - self.regularization_parameter * penalty_obj
  
imports: from __future__ import annotations
  import math
  from typing import Any, Callable, List, Optional
  import torch
  from botorch.acquisition.acquisition import AcquisitionFunction
  from botorch.acquisition.analytic import AnalyticAcquisitionFunction
  from botorch.acquisition.objective import GenericMCObjective
  from botorch.exceptions import UnsupportedError
  from torch import Tensor
label_desc: Use image node_id 2 for calling the PenalizedMCObjective obj's underlying member method code with example usage: obj.forward(samples, X) and returns: unknown