def test_constrained_expected_improvement(self, cuda=False): device = torch.device("cuda") if cuda else torch.device("cpu") for dtype in (torch.float, torch.double): # one constraint mean = torch.tensor([[-0.5, 0.0]], device=device, dtype=dtype).unsqueeze(dim=-2) variance = torch.ones(1, 2, device=device, dtype=dtype).unsqueeze(dim=-2) mm = MockModel(MockPosterior(mean=mean, variance=variance)) module = ConstrainedExpectedImprovement(model=mm, best_f=0.0, objective_index=0, constraints={1: [None, 0]}) X = torch.empty(1, 1, device=device, dtype=dtype) # dummy ei = module(X) ei_expected_unconstrained = torch.tensor(0.19780, device=device, dtype=dtype) ei_expected = ei_expected_unconstrained * 0.5 self.assertTrue(torch.allclose(ei, ei_expected, atol=1e-4)) # check that error raised if no constraints with self.assertRaises(ValueError): module = ConstrainedExpectedImprovement(model=mm, best_f=0.0, objective_index=0, constraints={}) # check that error raised if objective is a constraint with self.assertRaises(ValueError): module = ConstrainedExpectedImprovement( model=mm, best_f=0.0, objective_index=0, constraints={0: [None, 0]}) # check that error raised if constraint lower > upper with self.assertRaises(ValueError): module = ConstrainedExpectedImprovement( model=mm, best_f=0.0, objective_index=0, constraints={0: [1, 0]}) # three constraints N = torch.distributions.Normal(loc=0.0, scale=1.0) a = N.icdf( torch.tensor(0.75)) # get a so that P(-a <= N <= a) = 0.5 mean = torch.tensor([[-0.5, 0.0, 5.0, 0.0]], device=device, dtype=dtype).unsqueeze(dim=-2) variance = torch.ones(1, 4, device=device, dtype=dtype).unsqueeze(dim=-2) mm = MockModel(MockPosterior(mean=mean, variance=variance)) module = ConstrainedExpectedImprovement( model=mm, best_f=0.0, objective_index=0, constraints={ 1: [None, 0], 2: [5.0, None], 3: [-a, a] }, ) X = torch.empty(1, 1, device=device, dtype=dtype) # dummy ei = module(X) ei_expected_unconstrained = torch.tensor(0.19780, device=device, dtype=dtype) ei_expected = ei_expected_unconstrained * 0.5 * 0.5 * 0.5 self.assertTrue(torch.allclose(ei, ei_expected, atol=1e-4)) # test maximize module_min = ConstrainedExpectedImprovement( model=mm, best_f=0.0, objective_index=0, constraints={1: [None, 0]}, maximize=False, ) ei_min = module_min(X) ei_expected_unconstrained_min = torch.tensor(0.6978, device=device, dtype=dtype) ei_expected_min = ei_expected_unconstrained_min * 0.5 self.assertTrue(torch.allclose(ei_min, ei_expected_min, atol=1e-4)) # test invalid onstraints with self.assertRaises(ValueError): ConstrainedExpectedImprovement( model=mm, best_f=0.0, objective_index=0, constraints={1: [1.0, -1.0]}, )
def test_q_upper_confidence_bound_batch(self, cuda=False): # TODO: T41739913 Implement tests for all MCAcquisitionFunctions device = torch.device("cuda") if cuda else torch.device("cpu") for dtype in (torch.float, torch.double): samples = torch.zeros(2, 2, 1, device=device, dtype=dtype) samples[0, 0, 0] = 1.0 mm = MockModel(MockPosterior(samples=samples)) # X is a dummy and unused b/c of mocking X = torch.zeros(1, 1, 1, device=device, dtype=dtype) # test batch mode sampler = IIDNormalSampler(num_samples=2) acqf = qUpperConfidenceBound(model=mm, beta=0.5, sampler=sampler) res = acqf(X) self.assertEqual(res[0].item(), 1.0) self.assertEqual(res[1].item(), 0.0) # test batch mode, no resample sampler = IIDNormalSampler(num_samples=2, seed=12345) acqf = qUpperConfidenceBound(model=mm, beta=0.5, sampler=sampler) res = acqf(X) # 1-dim batch self.assertEqual(res[0].item(), 1.0) self.assertEqual(res[1].item(), 0.0) self.assertEqual(acqf.sampler.base_samples.shape, torch.Size([2, 1, 2, 1])) bs = acqf.sampler.base_samples.clone() acqf(X) self.assertTrue(torch.equal(acqf.sampler.base_samples, bs)) res = acqf(X.expand(2, 1, 1)) # 2-dim batch self.assertEqual(res[0].item(), 1.0) self.assertEqual(res[1].item(), 0.0) # the base samples should have the batch dim collapsed self.assertEqual(acqf.sampler.base_samples.shape, torch.Size([2, 1, 2, 1])) bs = acqf.sampler.base_samples.clone() acqf(X.expand(2, 1, 1)) self.assertTrue(torch.equal(acqf.sampler.base_samples, bs)) # test batch mode, qmc, no resample sampler = SobolQMCNormalSampler(num_samples=2) acqf = qUpperConfidenceBound(model=mm, beta=0.5, sampler=sampler) res = acqf(X) self.assertEqual(res[0].item(), 1.0) self.assertEqual(res[1].item(), 0.0) self.assertEqual(acqf.sampler.base_samples.shape, torch.Size([2, 1, 2, 1])) bs = acqf.sampler.base_samples.clone() acqf(X) self.assertTrue(torch.equal(acqf.sampler.base_samples, bs)) # test batch mode, qmc, resample sampler = SobolQMCNormalSampler(num_samples=2, resample=True) acqf = qUpperConfidenceBound(model=mm, beta=0.5, sampler=sampler) res = acqf(X) # 1-dim batch self.assertEqual(res[0].item(), 1.0) self.assertEqual(res[1].item(), 0.0) self.assertEqual(acqf.sampler.base_samples.shape, torch.Size([2, 1, 2, 1])) bs = acqf.sampler.base_samples.clone() acqf(X) self.assertFalse(torch.equal(acqf.sampler.base_samples, bs)) res = acqf(X.expand(2, 1, 1)) # 2-dim batch self.assertEqual(res[0].item(), 1.0) self.assertEqual(res[1].item(), 0.0) # the base samples should have the batch dim collapsed self.assertEqual(acqf.sampler.base_samples.shape, torch.Size([2, 1, 2, 1])) bs = acqf.sampler.base_samples.clone() acqf(X.expand(2, 1, 1)) self.assertFalse(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) res = acqf(X) X2 = torch.zeros(1, 1, 1, device=device, dtype=dtype, requires_grad=True) with warnings.catch_warnings(record=True) as ws: acqf.set_X_pending(X2) self.assertEqual(acqf.X_pending, X2) self.assertEqual(len(ws), 1) self.assertTrue(issubclass(ws[-1].category, BotorchWarning))
def test_expected_improvement_batch(self, cuda=False): device = torch.device("cuda") if cuda else torch.device("cpu") for dtype in (torch.float, torch.double): mean = torch.tensor([-0.5, 0.0, 0.5], device=device, dtype=dtype).view(3, 1, 1) variance = torch.ones(3, 1, 1, device=device, dtype=dtype) mm = MockModel(MockPosterior(mean=mean, variance=variance)) module = ExpectedImprovement(model=mm, best_f=0.0) X = torch.empty(3, 1, 1, device=device, dtype=dtype) # dummy ei = module(X) ei_expected = torch.tensor([0.19780, 0.39894, 0.69780], device=device, dtype=dtype) self.assertTrue(torch.allclose(ei, ei_expected, atol=1e-4)) # check for proper error if multi-output model mean2 = torch.rand(3, 1, 2, device=device, dtype=dtype) variance2 = torch.rand(3, 1, 2, device=device, dtype=dtype) mm2 = MockModel(MockPosterior(mean=mean2, variance=variance2)) module2 = ExpectedImprovement(model=mm2, best_f=0.0) with self.assertRaises(UnsupportedError): module2(X) # test objective (single-output) mean = torch.tensor([[[0.5]], [[0.25]]], device=device, dtype=dtype) covar = torch.tensor([[[[0.16]]], [[[0.125]]]], device=device, dtype=dtype) mvn = MultivariateNormal(mean, covar) p = GPyTorchPosterior(mvn) mm = MockModel(p) weights = torch.tensor([0.5], device=device, dtype=dtype) obj = ScalarizedObjective(weights) ei = ExpectedImprovement(model=mm, best_f=0.0, objective=obj) X = torch.rand(2, 1, 2, device=device, dtype=dtype) ei_expected = torch.tensor([[0.2601], [0.1500]], device=device, dtype=dtype) torch.allclose(ei(X), ei_expected, atol=1e-4) # test objective (multi-output) mean = torch.tensor([[[-0.25, 0.5]], [[0.2, -0.1]]], device=device, dtype=dtype) covar = torch.tensor( [[[0.5, 0.125], [0.125, 0.5]], [[0.25, -0.1], [-0.1, 0.25]]], device=device, dtype=dtype, ) mvn = MultitaskMultivariateNormal(mean, covar) p = GPyTorchPosterior(mvn) mm = MockModel(p) weights = torch.tensor([2.0, 1.0], device=device, dtype=dtype) obj = ScalarizedObjective(weights) ei = ExpectedImprovement(model=mm, best_f=0.0, objective=obj) X = torch.rand(2, 1, 2, device=device, dtype=dtype) ei_expected = torch.tensor([0.6910, 0.5371], device=device, dtype=dtype) torch.allclose(ei(X), ei_expected, atol=1e-4) # test bad objective class with self.assertRaises(UnsupportedError): ExpectedImprovement(model=mm, best_f=0.0, objective=IdentityMCObjective())
def test_q_upper_confidence_bound(self, cuda=False): device = torch.device("cuda") if cuda else torch.device("cpu") for dtype in (torch.float, torch.double): # the event shape is `b x q x t` = 1 x 1 x 1 samples = torch.zeros(1, 1, 1, device=device, dtype=dtype) 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, device=device, dtype=dtype) # basic test sampler = IIDNormalSampler(num_samples=2) acqf = qUpperConfidenceBound(model=mm, beta=0.5, sampler=sampler) res = acqf(X) self.assertEqual(res.item(), 0.0) # basic test, no resample sampler = IIDNormalSampler(num_samples=2, seed=12345) acqf = qUpperConfidenceBound(model=mm, beta=0.5, sampler=sampler) res = acqf(X) self.assertEqual(res.item(), 0.0) 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, no resample sampler = SobolQMCNormalSampler(num_samples=2) acqf = qUpperConfidenceBound(model=mm, beta=0.5, sampler=sampler) res = acqf(X) self.assertEqual(res.item(), 0.0) 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, qmc, resample sampler = SobolQMCNormalSampler(num_samples=2, resample=True) acqf = qUpperConfidenceBound(model=mm, beta=0.5, sampler=sampler) res = acqf(X) self.assertEqual(res.item(), 0.0) self.assertEqual(acqf.sampler.base_samples.shape, torch.Size([2, 1, 1, 1])) bs = acqf.sampler.base_samples.clone() acqf(X) self.assertFalse(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) res = acqf(X) X2 = torch.zeros(1, 1, 1, device=device, dtype=dtype, requires_grad=True) with warnings.catch_warnings(record=True) as ws: acqf.set_X_pending(X2) self.assertEqual(acqf.X_pending, X2) self.assertEqual(len(ws), 1) self.assertTrue(issubclass(ws[-1].category, BotorchWarning))
def test_q_simple_regret_batch(self, cuda=False): # the event shape is `b x q x t` = 2 x 2 x 1 device = torch.device("cuda") if cuda else torch.device("cpu") for dtype in (torch.float, torch.double): samples = torch.zeros(2, 2, 1, device=device, dtype=dtype) samples[0, 0, 0] = 1.0 mm = MockModel(MockPosterior(samples=samples)) # X is a dummy and unused b/c of mocking X = torch.zeros(1, 1, 1, device=device, dtype=dtype) # test batch mode sampler = IIDNormalSampler(num_samples=2) acqf = qSimpleRegret(model=mm, sampler=sampler) res = acqf(X) self.assertEqual(res[0].item(), 1.0) self.assertEqual(res[1].item(), 0.0) # test batch mode, no resample sampler = IIDNormalSampler(num_samples=2, seed=12345) acqf = qSimpleRegret(model=mm, sampler=sampler) res = acqf(X) # 1-dim batch self.assertEqual(res[0].item(), 1.0) self.assertEqual(res[1].item(), 0.0) self.assertEqual(acqf.sampler.base_samples.shape, torch.Size([2, 1, 2, 1])) bs = acqf.sampler.base_samples.clone() acqf(X) self.assertTrue(torch.equal(acqf.sampler.base_samples, bs)) res = acqf(X.expand(2, 1, 1)) # 2-dim batch self.assertEqual(res[0].item(), 1.0) self.assertEqual(res[1].item(), 0.0) # the base samples should have the batch dim collapsed self.assertEqual(acqf.sampler.base_samples.shape, torch.Size([2, 1, 2, 1])) bs = acqf.sampler.base_samples.clone() acqf(X.expand(2, 1, 1)) self.assertTrue(torch.equal(acqf.sampler.base_samples, bs)) # test batch mode, qmc, no resample sampler = SobolQMCNormalSampler(num_samples=2) acqf = qSimpleRegret(model=mm, sampler=sampler) res = acqf(X) self.assertEqual(res[0].item(), 1.0) self.assertEqual(res[1].item(), 0.0) self.assertEqual(acqf.sampler.base_samples.shape, torch.Size([2, 1, 2, 1])) bs = acqf.sampler.base_samples.clone() acqf(X) self.assertTrue(torch.equal(acqf.sampler.base_samples, bs)) # test batch mode, qmc, resample sampler = SobolQMCNormalSampler(num_samples=2, resample=True) acqf = qSimpleRegret(model=mm, sampler=sampler) res = acqf(X) # 1-dim batch self.assertEqual(res[0].item(), 1.0) self.assertEqual(res[1].item(), 0.0) self.assertEqual(acqf.sampler.base_samples.shape, torch.Size([2, 1, 2, 1])) bs = acqf.sampler.base_samples.clone() acqf(X) self.assertFalse(torch.equal(acqf.sampler.base_samples, bs)) res = acqf(X.expand(2, 1, 1)) # 2-dim batch self.assertEqual(res[0].item(), 1.0) self.assertEqual(res[1].item(), 0.0) # the base samples should have the batch dim collapsed self.assertEqual(acqf.sampler.base_samples.shape, torch.Size([2, 1, 2, 1])) bs = acqf.sampler.base_samples.clone() acqf(X.expand(2, 1, 1)) self.assertFalse(torch.equal(acqf.sampler.base_samples, bs))
def test_q_noisy_expected_improvement_batch(self, cuda=False): device = torch.device("cuda") if cuda else torch.device("cpu") for dtype in (torch.float, torch.double): # the event shape is `b x q x t` = 2 x 3 x 1 samples_noisy = torch.zeros(2, 3, 1, device=device, dtype=dtype) samples_noisy[0, 0, 0] = 1.0 mm_noisy = MockModel(MockPosterior(samples=samples_noisy)) # X is `q x d` = 1 x 1 X = torch.zeros(1, 1, 1, device=device, dtype=dtype) X_baseline = torch.zeros(1, 1, device=device, dtype=dtype) # test batch mode sampler = IIDNormalSampler(num_samples=2) acqf = qNoisyExpectedImprovement(model=mm_noisy, X_baseline=X_baseline, sampler=sampler) res = acqf(X) self.assertEqual(res[0].item(), 1.0) self.assertEqual(res[1].item(), 0.0) # test batch mode, no resample sampler = IIDNormalSampler(num_samples=2, seed=12345) acqf = qNoisyExpectedImprovement(model=mm_noisy, X_baseline=X_baseline, sampler=sampler) res = acqf(X) # 1-dim batch self.assertEqual(res[0].item(), 1.0) self.assertEqual(res[1].item(), 0.0) self.assertEqual(acqf.sampler.base_samples.shape, torch.Size([2, 1, 3, 1])) bs = acqf.sampler.base_samples.clone() acqf(X) self.assertTrue(torch.equal(acqf.sampler.base_samples, bs)) res = acqf(X.expand(2, 1, 1)) # 2-dim batch self.assertEqual(res[0].item(), 1.0) self.assertEqual(res[1].item(), 0.0) # the base samples should have the batch dim collapsed self.assertEqual(acqf.sampler.base_samples.shape, torch.Size([2, 1, 3, 1])) bs = acqf.sampler.base_samples.clone() acqf(X.expand(2, 1, 1)) self.assertTrue(torch.equal(acqf.sampler.base_samples, bs)) # test batch mode, qmc, no resample sampler = SobolQMCNormalSampler(num_samples=2) acqf = qNoisyExpectedImprovement(model=mm_noisy, X_baseline=X_baseline, sampler=sampler) res = acqf(X) self.assertEqual(res[0].item(), 1.0) self.assertEqual(res[1].item(), 0.0) self.assertEqual(acqf.sampler.base_samples.shape, torch.Size([2, 1, 3, 1])) bs = acqf.sampler.base_samples.clone() acqf(X) self.assertTrue(torch.equal(acqf.sampler.base_samples, bs)) # test X_pending w/ batch mode, qmc, resample sampler = SobolQMCNormalSampler(num_samples=2, resample=True, seed=12345) acqf = qNoisyExpectedImprovement(model=mm_noisy, X_baseline=X_baseline, sampler=sampler) res = acqf(X) # 1-dim batch self.assertEqual(res[0].item(), 1.0) self.assertEqual(res[1].item(), 0.0) self.assertEqual(acqf.sampler.base_samples.shape, torch.Size([2, 1, 3, 1])) bs = acqf.sampler.base_samples.clone() acqf(X) self.assertFalse(torch.equal(acqf.sampler.base_samples, bs)) res = acqf(X.expand(2, 1, 1)) # 2-dim batch self.assertEqual(res[0].item(), 1.0) self.assertEqual(res[1].item(), 0.0) # the base samples should have the batch dim collapsed self.assertEqual(acqf.sampler.base_samples.shape, torch.Size([2, 1, 3, 1])) bs = acqf.sampler.base_samples.clone() acqf(X.expand(2, 1, 1)) self.assertFalse(torch.equal(acqf.sampler.base_samples, bs))
def test_q_expected_improvement(self, cuda=False): device = torch.device("cuda") if cuda else torch.device("cpu") for dtype in (torch.float, torch.double): # the event shape is `b x q x t` = 1 x 1 x 1 samples = torch.zeros(1, 1, 1, device=device, dtype=dtype) 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, device=device, dtype=dtype) # basic test sampler = IIDNormalSampler(num_samples=2) acqf = qExpectedImprovement(model=mm, best_f=0, sampler=sampler) res = acqf(X) self.assertEqual(res.item(), 0.0) # test shifting best_f value acqf = qExpectedImprovement(model=mm, best_f=-1, sampler=sampler) res = acqf(X) self.assertEqual(res.item(), 1.0) # basic test, no resample sampler = IIDNormalSampler(num_samples=2, seed=12345) acqf = qExpectedImprovement(model=mm, best_f=0, sampler=sampler) res = acqf(X) self.assertEqual(res.item(), 0.0) 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, no resample sampler = SobolQMCNormalSampler(num_samples=2) acqf = qExpectedImprovement(model=mm, best_f=0, sampler=sampler) res = acqf(X) self.assertEqual(res.item(), 0.0) 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, qmc, resample sampler = SobolQMCNormalSampler(num_samples=2, resample=True) acqf = qExpectedImprovement(model=mm, best_f=0, sampler=sampler) res = acqf(X) self.assertEqual(res.item(), 0.0) self.assertEqual(acqf.sampler.base_samples.shape, torch.Size([2, 1, 1, 1])) bs = acqf.sampler.base_samples.clone() acqf(X) self.assertFalse(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) res = acqf(X) X2 = torch.zeros(1, 1, 1, device=device, dtype=dtype, requires_grad=True) with warnings.catch_warnings(record=True) as ws: acqf.set_X_pending(X2) self.assertEqual(acqf.X_pending, X2) self.assertEqual(len(ws), 1) self.assertTrue(issubclass(ws[-1].category, BotorchWarning)) # test bad objective type obj = ScalarizedObjective( weights=torch.rand(2, device=device, dtype=dtype)) with self.assertRaises(UnsupportedError): qExpectedImprovement(model=mm, best_f=0, sampler=sampler, objective=obj)
def test_q_noisy_expected_improvement(self, cuda=False): device = torch.device("cuda") if cuda else torch.device("cpu") for dtype in (torch.float, torch.double): # the event shape is `b x q x t` = 1 x 2 x 1 samples_noisy = torch.tensor([1.0, 0.0], device=device, dtype=dtype) samples_noisy = samples_noisy.view(1, 2, 1) # X_baseline is `q' x d` = 1 x 1 X_baseline = torch.zeros(1, 1, device=device, dtype=dtype) mm_noisy = MockModel(MockPosterior(samples=samples_noisy)) # X is `q x d` = 1 x 1 X = torch.zeros(1, 1, device=device, dtype=dtype) # basic test sampler = IIDNormalSampler(num_samples=2) acqf = qNoisyExpectedImprovement(model=mm_noisy, X_baseline=X_baseline, sampler=sampler) res = acqf(X) self.assertEqual(res.item(), 1.0) # basic test, no resample sampler = IIDNormalSampler(num_samples=2, seed=12345) acqf = qNoisyExpectedImprovement(model=mm_noisy, X_baseline=X_baseline, sampler=sampler) res = acqf(X) self.assertEqual(res.item(), 1.0) self.assertEqual(acqf.sampler.base_samples.shape, torch.Size([2, 1, 2, 1])) bs = acqf.sampler.base_samples.clone() acqf(X) self.assertTrue(torch.equal(acqf.sampler.base_samples, bs)) # basic test, qmc, no resample sampler = SobolQMCNormalSampler(num_samples=2) acqf = qNoisyExpectedImprovement(model=mm_noisy, X_baseline=X_baseline, sampler=sampler) res = acqf(X) self.assertEqual(res.item(), 1.0) self.assertEqual(acqf.sampler.base_samples.shape, torch.Size([2, 1, 2, 1])) bs = acqf.sampler.base_samples.clone() acqf(X) self.assertTrue(torch.equal(acqf.sampler.base_samples, bs)) # basic test, qmc, resample sampler = SobolQMCNormalSampler(num_samples=2, resample=True, seed=12345) acqf = qNoisyExpectedImprovement(model=mm_noisy, X_baseline=X_baseline, sampler=sampler) res = acqf(X) self.assertEqual(res.item(), 1.0) self.assertEqual(acqf.sampler.base_samples.shape, torch.Size([2, 1, 2, 1])) bs = acqf.sampler.base_samples.clone() acqf(X) self.assertFalse(torch.equal(acqf.sampler.base_samples, bs)) # basic test for X_pending and warning sampler = SobolQMCNormalSampler(num_samples=2) samples_noisy_pending = torch.tensor([1.0, 0.0, 0.0], device=device, dtype=dtype) samples_noisy_pending = samples_noisy_pending.view(1, 3, 1) mm_noisy_pending = MockModel( MockPosterior(samples=samples_noisy_pending)) acqf = qNoisyExpectedImprovement(model=mm_noisy_pending, X_baseline=X_baseline, sampler=sampler) 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) res = acqf(X) X2 = torch.zeros(1, 1, 1, device=device, dtype=dtype, requires_grad=True) with warnings.catch_warnings(record=True) as ws: acqf.set_X_pending(X2) self.assertEqual(acqf.X_pending, X2) self.assertEqual(len(ws), 1) self.assertTrue(issubclass(ws[-1].category, BotorchWarning))