code: def test_q_log_expected_improvement(self):
      self.assertIn(
          qLogExpectedImprovement,
          ACQF_INPUT_CONSTRUCTOR_REGISTRY.keys(),
      )
      for dtype in (torch.float, torch.double):
          tkwargs = {"device": self.device, "dtype": dtype}
          # the event shape is `b x q x t` = 1 x 1 x 1
          samples = torch.zeros(1, 1, 1, **tkwargs)
          mm = MockModel(MockPosterior(samples=samples))
          # X is `q x d` = 1 x 1. X is a dummy and unused b/c of mocking
          X = torch.zeros(1, 1, **tkwargs)
  
          # basic test
          sampler = IIDNormalSampler(sample_shape=torch.Size([2]))
          acqf = qExpectedImprovement(
              model=mm, best_f=0, sampler=sampler
          )
          log_acqf = qLogExpectedImprovement(
              model=mm, best_f=0, sampler=sampler
          )
          self.assertFalse(acqf._fat)  # different default behavior
          self.assertTrue(log_acqf._fat)
          # test initialization
          for k in ["objective", "sampler"]:
              self.assertIn(k, acqf._modules)
              self.assertIn(k, log_acqf._modules)
  
          res = acqf(X).item()
          self.assertEqual(res, 0.0)
          exp_log_res = log_acqf(X).exp().item()
          # Due to the smooth approximation, the value at zero should be close to, but
          # not exactly zero, and upper-bounded by the tau hyperparameter.
          self.assertTrue(0 < exp_log_res)
          self.assertTrue(exp_log_res <= log_acqf.tau_relu)
  
          # test shifting best_f value downward to see non-zero improvement
          best_f = -1
          acqf = qExpectedImprovement(
              model=mm, best_f=best_f, sampler=sampler
          )
          log_acqf = qLogExpectedImprovement(
              model=mm, best_f=best_f, sampler=sampler
          )
          res, exp_log_res = acqf(X), log_acqf(X).exp()
          expected_val = -best_f
  
          self.assertEqual(res.dtype, dtype)
          self.assertEqual(res.device.type, self.device.type)
          self.assertEqual(res.item(), expected_val)
          # Further away from zero, the value is numerically indistinguishable with
          # single precision arithmetic.
          self.assertEqual(exp_log_res.dtype, dtype)
          self.assertEqual(exp_log_res.device.type, self.device.type)
          self.assertTrue(expected_val <= exp_log_res.item())
          self.assertTrue(
              exp_log_res.item() <= expected_val + log_acqf.tau_relu
          )
  
          # test shifting best_f value upward to see advantage of LogEI
          best_f = 1
          acqf = qExpectedImprovement(
              model=mm, best_f=best_f, sampler=sampler
          )
          log_acqf = qLogExpectedImprovement(
              model=mm, best_f=best_f, sampler=sampler
          )
          res, log_res = acqf(X), log_acqf(X)
          exp_log_res = log_res.exp()
          expected_val = 0
          self.assertEqual(res.item(), expected_val)
          self.assertTrue(expected_val <= exp_log_res.item())
          self.assertTrue(
              exp_log_res.item() <= expected_val + log_acqf.tau_relu
          )
          # However, the log value is large and negative with non-vanishing gradients
          self.assertGreater(-1, log_res.item())
          self.assertGreater(log_res.item(), -100)
  
          # NOTE: The following tests are adapted from the qEI tests.
          # basic test, no resample
          sampler = IIDNormalSampler(
              sample_shape=torch.Size([2]), seed=12345
          )
          acqf = qLogExpectedImprovement(
              model=mm, best_f=0, sampler=sampler
          )
          res = acqf(X)
          self.assertTrue(0 < res.exp().item())
          self.assertTrue(res.exp().item() < acqf.tau_relu)
          self.assertEqual(
              acqf.sampler.base_samples.shape, torch.Size([2, 1, 1, 1])
          )
          bs = acqf.sampler.base_samples.clone()
          res = acqf(X)
          self.assertTrue(torch.equal(acqf.sampler.base_samples, bs))
  
          # basic test, qmc
          sampler = SobolQMCNormalSampler(sample_shape=torch.Size([2]))
          acqf = qLogExpectedImprovement(
              model=mm, best_f=0, sampler=sampler
          )
          res = acqf(X)
          self.assertTrue(0 < res.exp().item())
          self.assertTrue(res.exp().item() < acqf.tau_relu)
          self.assertEqual(
              acqf.sampler.base_samples.shape, torch.Size([2, 1, 1, 1])
          )
          bs = acqf.sampler.base_samples.clone()
          acqf(X)
          self.assertTrue(torch.equal(acqf.sampler.base_samples, bs))
  
          # basic test for X_pending and warning
          acqf.set_X_pending()
          self.assertIsNone(acqf.X_pending)
          acqf.set_X_pending(None)
          self.assertIsNone(acqf.X_pending)
          acqf.set_X_pending(X)
          self.assertEqual(acqf.X_pending, X)
          mm._posterior._samples = torch.zeros(1, 2, 1, **tkwargs)
          res = acqf(X)
          X2 = torch.zeros(1, 1, 1, **tkwargs, requires_grad=True)
          with warnings.catch_warnings(
              record=True
          ) as ws, settings.debug(True):
              acqf.set_X_pending(X2)
              self.assertEqual(acqf.X_pending, X2)
              self.assertEqual(
                  sum(
                      issubclass(w.category, BotorchWarning) for w in ws
                  ),
                  1,
              )
  
          # testing with illegal taus
          with self.assertRaisesRegex(
              ValueError, "tau_max is not a scalar:"
          ):
              qLogExpectedImprovement(
                  model=mm, best_f=0, tau_max=torch.tensor([1, 2])
              )
          with self.assertRaisesRegex(
              ValueError, "tau_relu is non-positive:"
          ):
              qLogExpectedImprovement(model=mm, best_f=0, tau_relu=-2)
  
imports: import warnings
  from copy import deepcopy
  from itertools import product
  from math import pi
  from unittest import mock
  import torch
  from botorch import settings
  from botorch.acquisition import AcquisitionFunction, LogImprovementMCAcquisitionFunction, qLogExpectedImprovement, qLogNoisyExpectedImprovement
  from botorch.acquisition.analytic import ExpectedImprovement, LogExpectedImprovement, LogNoisyExpectedImprovement, NoisyExpectedImprovement
  from botorch.acquisition.input_constructors import ACQF_INPUT_CONSTRUCTOR_REGISTRY
  from botorch.acquisition.monte_carlo import qExpectedImprovement, qNoisyExpectedImprovement
  from botorch.acquisition.multi_objective.logei import qLogNoisyExpectedHypervolumeImprovement
  from botorch.acquisition.objective import ConstrainedMCObjective, GenericMCObjective, IdentityMCObjective, PosteriorTransform, ScalarizedPosteriorTransform
  from botorch.acquisition.utils import prune_inferior_points
  from botorch.exceptions import BotorchWarning, UnsupportedError
  from botorch.exceptions.errors import BotorchError
  from botorch.models import ModelListGP, SingleTaskGP
  from botorch.models.gp_regression import FixedNoiseGP
  from botorch.sampling.normal import IIDNormalSampler, SobolQMCNormalSampler
  from botorch.utils.low_rank import sample_cached_cholesky
  from botorch.utils.testing import BotorchTestCase, MockModel, MockPosterior
  from botorch.utils.transforms import standardize
  from torch import Tensor
label_desc: Use image node_id 1 for calling the TestQLogExpectedImprovement obj's underlying member method code with example usage: obj.test_q_log_expected_improvement() without return types