class_docstr: A wrapper around AcquisitionFunctions to add proximal weighting of the
  acquisition function. The acquisition function is
  weighted via a squared exponential centered at the last training point,
  with varying lengthscales corresponding to `proximal_weights`. Can only be used
  with acquisition functions based on single batch models. Acquisition functions
  must be positive or `beta` must be specified to apply a SoftPlus transform before
  proximal weighting.
  
  Small values of `proximal_weights` corresponds to strong biasing towards recently
  observed points, which smoothes optimization with a small potential decrese in
  convergence rate.
  
  
  
  Example:
      >>> model = SingleTaskGP(train_X, train_Y)
      >>> EI = ExpectedImprovement(model, best_f=0.0)
      >>> proximal_weights = torch.ones(d)
      >>> EI_proximal = ProximalAcquisitionFunction(EI, proximal_weights)
      >>> eip = EI_proximal(test_X)
class_docstr_tok: ["A","wrapper","around","AcquisitionFunctions","to","add","proximal","weighting","of","the","acquisition","function",".","The","acquisition","function","is","weighted","via","a","squared","exponential","centered","at","the","last","training","point",",","with","varying","lengthscales","corresponding","to","`","proximal_weights","`",".","Can","only","be","used","with","acquisition","functions","based","on","single","batch","models",".","Acquisition","functions","must","be","positive","or","`","beta","`","must","be","specified","to","apply","a","SoftPlus","transform","before","proximal","weighting",".","Small","values","of","`","proximal_weights","`","corresponds","to","strong","biasing","towards","recently","observed","points",",","which","smoothes","optimization","with","a","small","potential","decrese","in","convergence","rate",".","Example",":",">",">",">","model","=","SingleTaskGP","(","train_X",",","train_Y",")",">",">",">","EI","=","ExpectedImprovement","(","model",",","best_f=0.0",")",">",">",">","proximal_weights","=","torch.ones","(","d",")",">",">",">","EI_proximal","=","ProximalAcquisitionFunction","(","EI",",","proximal_weights",")",">",">",">","eip","=","EI_proximal","(","test_X",")"]
docstr: Evaluate base acquisition function with proximal weighting.
  
  Args:
      X: Input tensor of feature dimension `d` .
  
  Returns:
      Base acquisition function evaluated on tensor `X` multiplied by proximal
      weighting.
docstr_tok: ["Evaluate","base","acquisition","function","with","proximal","weighting",".","Args",":","X",":","Input","tensor","of","feature","dimension","`","d","`",".","Returns",":","Base","acquisition","function","evaluated","on","tensor","`","X","`","multiplied","by","proximal","weighting","."]
code: def forward(self, X: Tensor) -> Tensor:
      r"""Evaluate base acquisition function with proximal weighting.
  
      Args:
          X: Input tensor of feature dimension `d` .
  
      Returns:
          Base acquisition function evaluated on tensor `X` multiplied by proximal
          weighting.
      """
      model = self.acq_func.model
  
      train_inputs = model.train_inputs[0]
  
      # if the model is ModelListGP then get the first model
      if isinstance(model, ModelListGP):
          train_inputs = train_inputs[0]
          model = model.models[0]
  
      # if the model has more than one output get the first copy of training inputs
      if (
          isinstance(model, BatchedMultiOutputGPyTorchModel)
          and model.num_outputs > 1
      ):
          train_inputs = train_inputs[0]
  
      input_transform = _get_input_transform(model)
  
      last_X = train_inputs[-1].reshape(1, 1, -1)
  
      # if transformed_weighting, transform X to calculate diff
      # (proximal weighting in transformed space)
      # otherwise,un-transform the last observed point to real space
      # (proximal weighting in real space)
      if input_transform is not None:
          if self.transformed_weighting:
              # transformed space weighting
              diff = input_transform.transform(X) - last_X
          else:
              # real space weighting
              diff = X - input_transform.untransform(last_X)
  
      else:
          # no transformation
          diff = X - last_X
  
      M = torch.linalg.norm(diff / self.proximal_weights, dim=-1) ** 2
      proximal_acq_weight = torch.exp(-0.5 * M)
  
      base_acqf = self.acq_func(X)
      if self.beta is None:
          if torch.any(base_acqf < 0):
              raise RuntimeError(
                  "Cannot use proximal biasing for negative "
                  "acquisition function values, set a value for beta to "
                  "fix this with a softplus transform"
              )
  
      else:
          base_acqf = torch.nn.functional.softplus(
              base_acqf, beta=self.beta
          )
  
      return base_acqf * proximal_acq_weight.flatten()
  
file_path: botorch/botorch/acquisition/proximal.py
imports: from __future__ import annotations
  from typing import Optional
  import torch
  from botorch.acquisition import AcquisitionFunction
  from botorch.exceptions.errors import UnsupportedError
  from botorch.models import ModelListGP
  from botorch.models.gpytorch import BatchedMultiOutputGPyTorchModel
  from botorch.models.model import Model
  from botorch.models.transforms.input import InputTransform
  from botorch.utils import t_batch_mode_transform
  from torch import Tensor
  from torch.nn import Module
label_desc: Use image node_id 2 for calling the ProximalAcquisitionFunction obj's underlying member method code with example usage: obj.forward(X) and returns: unknown