class_docstr: Laplace-approximated marginal log likelihood/evidence for PairwiseGP
  
  See (12) from [Chu2005preference]_.
class_docstr_tok: ["Laplace-approximated","marginal","log","likelihood\/evidence","for","PairwiseGP","See","(","12",")","from","[","Chu2005preference","]","_","."]
docstr: Calculate approximated log evidence, i.e., log(P(D|theta))
  
  Note that post will be based on the consolidated/deduped datapoints for
  numerical stability, but comp will still be the unconsolidated comparisons
  so that it's still compatible with fit_gpytorch_*.
  
  Args:
      post: training posterior distribution from self.model (after consolidation)
      comp: Comparisons pairs (before consolidation)
  
  Returns:
      The approximated evidence, i.e., the marginal log likelihood
docstr_tok: ["Calculate","approximated","log","evidence",",","i.e.",",","log","(","P","(","D|theta",")",")","Note","that","post","will","be","based","on","the","consolidated\/deduped","datapoints","for","numerical","stability",",","but","comp","will","still","be","the","unconsolidated","comparisons","so","that","it","'s","still","compatible","with","fit_gpytorch_","*",".","Args",":","post",":","training","posterior","distribution","from","self.model","(","after","consolidation",")","comp",":","Comparisons","pairs","(","before","consolidation",")","Returns",":","The","approximated","evidence",",","i.e.",",","the","marginal","log","likelihood"]
code: def forward(self, post: Posterior, comp: Tensor) -> Tensor:
      r"""Calculate approximated log evidence, i.e., log(P(D|theta))
  
      Note that post will be based on the consolidated/deduped datapoints for
      numerical stability, but comp will still be the unconsolidated comparisons
      so that it's still compatible with fit_gpytorch_*.
  
      Args:
          post: training posterior distribution from self.model (after consolidation)
          comp: Comparisons pairs (before consolidation)
  
      Returns:
          The approximated evidence, i.e., the marginal log likelihood
      """
  
      model = self.model
      likelihood = self.likelihood
      if comp is not model.unconsolidated_comparisons:
          raise RuntimeError("Must train on training data")
  
      f_map = post.mean.squeeze(-1)
  
      log_likelihood = likelihood.log_p(utility=f_map, D=model.D)
      neg_log_likelihood_sum = -(torch.sum(log_likelihood, dim=-1))
  
      # 1/2 f_map^T @ covar_inv @ f_map
      inv_prod = torch.cholesky_solve(
          f_map.unsqueeze(-1), model.covar_chol
      )
      log_prior = 0.5 * (f_map.unsqueeze(-2) @ inv_prod).squeeze(
          -1
      ).squeeze(-1)
      log_posterior = neg_log_likelihood_sum + log_prior
      # log_posterior is the S loss function in [Chu2005preference]_
      log_posterior = -log_posterior.clamp(min=0)
  
      mll = model.covar @ model.likelihood_hess
      mll = mll + torch.diag_embed(
          torch.ones(mll.shape[:-1], device=mll.device, dtype=mll.dtype)
      )
      mll = -0.5 * torch.logdet(mll)
  
      mll = mll + log_posterior
  
      # Sum up mll first so that when adding parameter prior probs it won't
      # propagate and double count
      mll = mll.sum()
  
      # Add log probs of priors on the (functions of) parameters
      for _, module, prior, closure, _ in self.named_priors():
          mll = mll.add(prior.log_prob(closure(module)).sum())
  
      return mll
  
imports: from __future__ import annotations
  import warnings
  from copy import deepcopy
  from typing import Any, Dict, Iterable, List, Optional, Tuple, Union
  import numpy
  import torch
  from botorch.acquisition.objective import PosteriorTransform
  from botorch.exceptions import UnsupportedError
  from botorch.exceptions.warnings import _get_single_precision_warning, InputDataWarning
  from botorch.models.likelihoods.pairwise import PairwiseLikelihood, PairwiseProbitLikelihood
  from botorch.models.model import FantasizeMixin, Model
  from botorch.models.transforms.input import InputTransform
  from botorch.models.utils.assorted import consolidate_duplicates
  from botorch.posteriors.gpytorch import GPyTorchPosterior
  from botorch.posteriors.posterior import Posterior
  from gpytorch import settings
  from gpytorch.constraints import GreaterThan, Interval
  from gpytorch.distributions.multivariate_normal import MultivariateNormal
  from gpytorch.kernels.rbf_kernel import RBFKernel
  from gpytorch.kernels.scale_kernel import ScaleKernel
  from gpytorch.means.constant_mean import ConstantMean
  from gpytorch.mlls import MarginalLogLikelihood
  from gpytorch.models.gp import GP
  from gpytorch.priors.smoothed_box_prior import SmoothedBoxPrior
  from gpytorch.priors.torch_priors import GammaPrior
  from linear_operator.operators import LinearOperator, RootLinearOperator
  from linear_operator.utils.cholesky import psd_safe_cholesky
  from linear_operator.utils.errors import NotPSDError
  from scipy import optimize
  from torch import float32, float64, Tensor
  from torch.nn.modules.module import _IncompatibleKeys
label_desc: Use image node_id 2 for calling the PairwiseLaplaceMarginalLogLikelihood obj's underlying member method code with example usage: obj.forward(post, comp) and returns: mll