diff --git a/test/optim/test_initializers.py b/test/optim/test_initializers.py index f12cdf6733..8f78e5b5a6 100644 --- a/test/optim/test_initializers.py +++ b/test/optim/test_initializers.py @@ -159,7 +159,7 @@ def test_gen_batch_initial_conditions(self): self.assertEqual(raw_samps.shape, expected_raw_samps_shape) def test_gen_batch_initial_conditions_highdim(self): - d = 120 + d = 2200 # 2200 * 10 (q) > 21201 (sobol max dim) bounds = torch.stack([torch.zeros(d), torch.ones(d)]) for dtype in (torch.float, torch.double): bounds = bounds.to(device=self.device, dtype=dtype) diff --git a/test/sampling/test_qmc.py b/test/sampling/test_qmc.py index 947cec6ef2..f86861e424 100644 --- a/test/sampling/test_qmc.py +++ b/test/sampling/test_qmc.py @@ -4,117 +4,80 @@ # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +import itertools import math import numpy as np import torch from botorch.sampling.qmc import MultivariateNormalQMCEngine, NormalQMCEngine -from botorch.utils.sampling import manual_seed from botorch.utils.testing import BotorchTestCase from scipy.stats import shapiro class NormalQMCTests(BotorchTestCase): def test_NormalQMCEngine(self): - # d = 1 - engine = NormalQMCEngine(d=1) - samples = engine.draw() - self.assertEqual(samples.dtype, torch.float) - self.assertEqual(samples.shape, torch.Size([1, 1])) - samples = engine.draw(n=5) - self.assertEqual(samples.shape, torch.Size([5, 1])) - # d = 2 - engine = NormalQMCEngine(d=2) - samples = engine.draw() - self.assertEqual(samples.shape, torch.Size([1, 2])) - samples = engine.draw(n=5) - self.assertEqual(samples.shape, torch.Size([5, 2])) - # test double dtype - samples = engine.draw(dtype=torch.double) - self.assertEqual(samples.dtype, torch.double) + for d in (1, 2): + engine = NormalQMCEngine(d=d) + samples = engine.draw() + self.assertEqual(samples.dtype, torch.float) + self.assertEqual(samples.shape, torch.Size([1, d])) + samples = engine.draw(n=5) + self.assertEqual(samples.shape, torch.Size([5, d])) + # test double dtype + samples = engine.draw(dtype=torch.double) + self.assertEqual(samples.dtype, torch.double) + self.assertEqual(samples.shape, torch.Size([1, d])) def test_NormalQMCEngineInvTransform(self): - # d = 1 - engine = NormalQMCEngine(d=1, inv_transform=True) - samples = engine.draw() - self.assertEqual(samples.dtype, torch.float) - self.assertEqual(samples.shape, torch.Size([1, 1])) - samples = engine.draw(n=5) - self.assertEqual(samples.shape, torch.Size([5, 1])) - # d = 2 - engine = NormalQMCEngine(d=2, inv_transform=True) - samples = engine.draw() - self.assertEqual(samples.shape, torch.Size([1, 2])) - samples = engine.draw(n=5) - self.assertEqual(samples.shape, torch.Size([5, 2])) - # test double dtype - samples = engine.draw(dtype=torch.double) - self.assertEqual(samples.dtype, torch.double) + for d in (1, 2): + engine = NormalQMCEngine(d=d, inv_transform=True) + samples = engine.draw() + self.assertEqual(samples.dtype, torch.float) + self.assertEqual(samples.shape, torch.Size([1, d])) + samples = engine.draw(n=5) + self.assertEqual(samples.shape, torch.Size([5, d])) + # test double dtype + samples = engine.draw(dtype=torch.double) + self.assertEqual(samples.dtype, torch.double) + self.assertEqual(samples.shape, torch.Size([1, d])) def test_NormalQMCEngineSeeded(self): # test even dimension engine = NormalQMCEngine(d=2, seed=12345) samples = engine.draw(n=2) self.assertEqual(samples.dtype, torch.float) - samples_expected = torch.tensor( - [[-0.63099602, -1.32950772], [0.29625805, 1.86425618]] - ) - self.assertTrue(torch.allclose(samples, samples_expected)) + self.assertEqual(samples.shape, torch.Size([2, 2])) # test odd dimension engine = NormalQMCEngine(d=3, seed=12345) samples = engine.draw(n=2) - samples_expected = torch.tensor( - [ - [1.83169884, -1.40473647, 0.24334828], - [0.36596099, 1.2987395, -1.47556275], - ] - ) - self.assertTrue(torch.allclose(samples, samples_expected)) + self.assertEqual(samples.shape, torch.Size([2, 3])) def test_NormalQMCEngineSeededOut(self): # test even dimension engine = NormalQMCEngine(d=2, seed=12345) - out = torch.empty(2, 2) + out = torch.zeros(2, 2) self.assertIsNone(engine.draw(n=2, out=out)) - samples_expected = torch.tensor( - [[-0.63099602, -1.32950772], [0.29625805, 1.86425618]] - ) - self.assertTrue(torch.allclose(out, samples_expected)) + self.assertTrue(torch.all(out != 0)) # test odd dimension engine = NormalQMCEngine(d=3, seed=12345) out = torch.empty(2, 3) self.assertIsNone(engine.draw(n=2, out=out)) - samples_expected = torch.tensor( - [ - [1.83169884, -1.40473647, 0.24334828], - [0.36596099, 1.2987395, -1.47556275], - ] - ) - self.assertTrue(torch.allclose(out, samples_expected)) + self.assertTrue(torch.all(out != 0)) def test_NormalQMCEngineSeededInvTransform(self): # test even dimension engine = NormalQMCEngine(d=2, seed=12345, inv_transform=True) samples = engine.draw(n=2) self.assertEqual(samples.dtype, torch.float) - samples_expected = torch.tensor( - [[-0.41622922, 0.46622792], [-0.96063897, -0.75568963]] - ) - self.assertTrue(torch.allclose(samples, samples_expected)) + self.assertEqual(samples.shape, torch.Size([2, 2])) # test odd dimension engine = NormalQMCEngine(d=3, seed=12345, inv_transform=True) samples = engine.draw(n=2) - samples_expected = torch.tensor( - [ - [-1.40525266, 1.37652443, -0.8519666], - [-0.166497, -2.3153681, -0.15975676], - ] - ) - self.assertTrue(torch.allclose(samples, samples_expected)) + self.assertEqual(samples.shape, torch.Size([2, 3])) def test_NormalQMCEngineShapiro(self): engine = NormalQMCEngine(d=2, seed=12345) - samples = engine.draw(n=250) + samples = engine.draw(n=256) self.assertEqual(samples.dtype, torch.float) self.assertTrue(torch.all(torch.abs(samples.mean(dim=0)) < 1e-2)) self.assertTrue(torch.all(torch.abs(samples.std(dim=0) - 1) < 1e-2)) @@ -128,7 +91,7 @@ def test_NormalQMCEngineShapiro(self): def test_NormalQMCEngineShapiroInvTransform(self): engine = NormalQMCEngine(d=2, seed=12345, inv_transform=True) - samples = engine.draw(n=250) + samples = engine.draw(n=256) self.assertEqual(samples.dtype, torch.float) self.assertTrue(torch.all(torch.abs(samples.mean(dim=0)) < 1e-2)) self.assertTrue(torch.all(torch.abs(samples.std(dim=0) - 1) < 1e-2)) @@ -175,166 +138,78 @@ def test_MultivariateNormalQMCEngineSymmetric(self): MultivariateNormalQMCEngine(mean=mean, cov=cov) def test_MultivariateNormalQMCEngine(self): - for dtype in (torch.float, torch.double): - - # d = 1 scalar - mean = torch.tensor([0], device=self.device, dtype=dtype) - cov = torch.tensor([[5]], device=self.device, dtype=dtype) - engine = MultivariateNormalQMCEngine(mean=mean, cov=cov) - samples = engine.draw() - self.assertEqual(samples.dtype, dtype) - self.assertEqual(samples.device.type, self.device.type) - self.assertEqual(samples.shape, torch.Size([1, 1])) - samples = engine.draw(n=5) - self.assertEqual(samples.shape, torch.Size([5, 1])) - - # d = 2 list - mean = torch.tensor([0, 1], device=self.device, dtype=dtype) - cov = torch.eye(2, device=self.device, dtype=dtype) + for d, dtype in itertools.product((1, 2, 3), (torch.float, torch.double)): + mean = torch.rand(d, device=self.device, dtype=dtype) + cov = torch.eye(d, device=self.device, dtype=dtype) engine = MultivariateNormalQMCEngine(mean=mean, cov=cov) samples = engine.draw() self.assertEqual(samples.dtype, dtype) self.assertEqual(samples.device.type, self.device.type) - self.assertEqual(samples.shape, torch.Size([1, 2])) + self.assertEqual(samples.shape, torch.Size([1, d])) samples = engine.draw(n=5) - self.assertEqual(samples.shape, torch.Size([5, 2])) - - # d = 3 Tensor - mean = torch.tensor([0, 1, 2], device=self.device, dtype=dtype) - cov = torch.eye(3, device=self.device, dtype=dtype) - engine = MultivariateNormalQMCEngine(mean=mean, cov=cov) - samples = engine.draw() - self.assertEqual(samples.dtype, dtype) - self.assertEqual(samples.device.type, self.device.type) - self.assertEqual(samples.shape, torch.Size([1, 3])) - samples = engine.draw(n=5) - self.assertEqual(samples.shape, torch.Size([5, 3])) + self.assertEqual(samples.shape, torch.Size([5, d])) def test_MultivariateNormalQMCEngineInvTransform(self): - for dtype in (torch.float, torch.double): - - # d = 1 scalar - mean = torch.tensor([0], device=self.device, dtype=dtype) - cov = torch.tensor([[5]], device=self.device, dtype=dtype) + for d, dtype in itertools.product((1, 2, 3), (torch.float, torch.double)): + mean = torch.rand(d, device=self.device, dtype=dtype) + cov = torch.eye(d, device=self.device, dtype=dtype) engine = MultivariateNormalQMCEngine(mean=mean, cov=cov, inv_transform=True) samples = engine.draw() self.assertEqual(samples.dtype, dtype) self.assertEqual(samples.device.type, self.device.type) - self.assertEqual(samples.shape, torch.Size([1, 1])) + self.assertEqual(samples.shape, torch.Size([1, d])) samples = engine.draw(n=5) - self.assertEqual(samples.shape, torch.Size([5, 1])) - - # d = 2 list - mean = torch.tensor([0, 1], device=self.device, dtype=dtype) - cov = torch.eye(2, device=self.device, dtype=dtype) - engine = MultivariateNormalQMCEngine(mean=mean, cov=cov, inv_transform=True) - samples = engine.draw() - self.assertEqual(samples.dtype, dtype) - self.assertEqual(samples.device.type, self.device.type) - self.assertEqual(samples.shape, torch.Size([1, 2])) - samples = engine.draw(n=5) - self.assertEqual(samples.shape, torch.Size([5, 2])) - - # d = 3 Tensor - mean = torch.tensor([0, 1, 2], device=self.device, dtype=dtype) - cov = torch.eye(3, device=self.device, dtype=dtype) - engine = MultivariateNormalQMCEngine(mean=mean, cov=cov, inv_transform=True) - samples = engine.draw() - self.assertEqual(samples.dtype, dtype) - self.assertEqual(samples.device.type, self.device.type) - self.assertEqual(samples.shape, torch.Size([1, 3])) - samples = engine.draw(n=5) - self.assertEqual(samples.shape, torch.Size([5, 3])) + self.assertEqual(samples.shape, torch.Size([5, d])) def test_MultivariateNormalQMCEngineSeeded(self): for dtype in (torch.float, torch.double): # test even dimension - with manual_seed(54321): - a = torch.randn(2, 2) - cov = a @ a.transpose(-1, -2) + torch.rand(2).diag() - + a = torch.randn(2, 2) + cov = a @ a.transpose(-1, -2) + torch.rand(2).diag() mean = torch.zeros(2, device=self.device, dtype=dtype) cov = cov.to(device=self.device, dtype=dtype) engine = MultivariateNormalQMCEngine(mean=mean, cov=cov, seed=12345) samples = engine.draw(n=2) self.assertEqual(samples.dtype, dtype) self.assertEqual(samples.device.type, self.device.type) - samples_expected = torch.tensor( - [[-0.849047422, -0.713852942], [0.398635030, 1.350660801]], - device=self.device, - dtype=dtype, - ) - self.assertTrue(torch.allclose(samples, samples_expected)) # test odd dimension - with manual_seed(54321): - a = torch.randn(3, 3) - cov = a @ a.transpose(-1, -2) + torch.rand(3).diag() - + a = torch.randn(3, 3) + cov = a @ a.transpose(-1, -2) + torch.rand(3).diag() mean = torch.zeros(3, device=self.device, dtype=dtype) cov = cov.to(device=self.device, dtype=dtype) engine = MultivariateNormalQMCEngine(mean, cov, seed=12345) samples = engine.draw(n=2) self.assertEqual(samples.dtype, dtype) self.assertEqual(samples.device.type, self.device.type) - samples_expected = torch.tensor( - [ - [3.113158941, -3.262257099, -0.819938779], - [0.621987879, 2.352285624, -1.992680788], - ], - device=self.device, - dtype=dtype, - ) - self.assertTrue(torch.allclose(samples, samples_expected)) def test_MultivariateNormalQMCEngineSeededOut(self): for dtype in (torch.float, torch.double): - # test even dimension - with manual_seed(54321): - a = torch.randn(2, 2) - cov = a @ a.transpose(-1, -2) + torch.rand(2).diag() - + a = torch.randn(2, 2) + cov = a @ a.transpose(-1, -2) + torch.rand(2).diag() mean = torch.zeros(2, device=self.device, dtype=dtype) cov = cov.to(device=self.device, dtype=dtype) engine = MultivariateNormalQMCEngine(mean=mean, cov=cov, seed=12345) - out = torch.empty(2, 2, device=self.device, dtype=dtype) + out = torch.zeros(2, 2, device=self.device, dtype=dtype) self.assertIsNone(engine.draw(n=2, out=out)) - samples_expected = torch.tensor( - [[-0.849047422, -0.713852942], [0.398635030, 1.350660801]], - device=self.device, - dtype=dtype, - ) - self.assertTrue(torch.allclose(out, samples_expected)) - + self.assertTrue(torch.all(out != 0)) # test odd dimension - with manual_seed(54321): - a = torch.randn(3, 3) - cov = a @ a.transpose(-1, -2) + torch.rand(3).diag() - + a = torch.randn(3, 3) + cov = a @ a.transpose(-1, -2) + torch.rand(3).diag() mean = torch.zeros(3, device=self.device, dtype=dtype) cov = cov.to(device=self.device, dtype=dtype) engine = MultivariateNormalQMCEngine(mean, cov, seed=12345) - out = torch.empty(2, 3, device=self.device, dtype=dtype) + out = torch.zeros(2, 3, device=self.device, dtype=dtype) self.assertIsNone(engine.draw(n=2, out=out)) - samples_expected = torch.tensor( - [ - [3.113158941, -3.262257099, -0.819938779], - [0.621987879, 2.352285624, -1.992680788], - ], - device=self.device, - dtype=dtype, - ) - self.assertTrue(torch.allclose(out, samples_expected)) + self.assertTrue(torch.all(out != 0)) def test_MultivariateNormalQMCEngineSeededInvTransform(self): for dtype in (torch.float, torch.double): # test even dimension - with manual_seed(54321): - a = torch.randn(2, 2) - cov = a @ a.transpose(-1, -2) + torch.rand(2).diag() - + a = torch.randn(2, 2) + cov = a @ a.transpose(-1, -2) + torch.rand(2).diag() mean = torch.zeros(2, device=self.device, dtype=dtype) cov = cov.to(device=self.device, dtype=dtype) engine = MultivariateNormalQMCEngine( @@ -343,18 +218,9 @@ def test_MultivariateNormalQMCEngineSeededInvTransform(self): samples = engine.draw(n=2) self.assertEqual(samples.dtype, dtype) self.assertEqual(samples.device.type, self.device.type) - samples_expected = torch.tensor( - [[-0.560064316, 0.629113674], [-1.292604208, -0.048077226]], - device=self.device, - dtype=dtype, - ) - self.assertTrue(torch.allclose(samples, samples_expected)) - # test odd dimension - with manual_seed(54321): - a = torch.randn(3, 3) - cov = a @ a.transpose(-1, -2) + torch.rand(3).diag() - + a = torch.randn(3, 3) + cov = a @ a.transpose(-1, -2) + torch.rand(3).diag() mean = torch.zeros(3, device=self.device, dtype=dtype) cov = cov.to(device=self.device, dtype=dtype) engine = MultivariateNormalQMCEngine( @@ -363,15 +229,6 @@ def test_MultivariateNormalQMCEngineSeededInvTransform(self): samples = engine.draw(n=2) self.assertEqual(samples.dtype, dtype) self.assertEqual(samples.device.type, self.device.type) - samples_expected = torch.tensor( - [ - [-2.388370037, 3.071142435, -0.319439292], - [-0.282978594, -4.350236893, -1.085214734], - ], - device=self.device, - dtype=dtype, - ) - self.assertTrue(torch.allclose(samples, samples_expected)) def test_MultivariateNormalQMCEngineShapiro(self): for dtype in (torch.float, torch.double): @@ -379,7 +236,7 @@ def test_MultivariateNormalQMCEngineShapiro(self): mean = torch.zeros(2, device=self.device, dtype=dtype) cov = torch.eye(2, device=self.device, dtype=dtype) engine = MultivariateNormalQMCEngine(mean=mean, cov=cov, seed=12345) - samples = engine.draw(n=250) + samples = engine.draw(n=256) self.assertEqual(samples.dtype, dtype) self.assertEqual(samples.device.type, self.device.type) self.assertTrue(torch.all(torch.abs(samples.mean(dim=0)) < 1e-2)) @@ -399,7 +256,7 @@ def test_MultivariateNormalQMCEngineShapiro(self): [[1.5, 0.5], [0.5, 1.5]], device=self.device, dtype=dtype ) engine = MultivariateNormalQMCEngine(mean=mean, cov=cov, seed=12345) - samples = engine.draw(n=250) + samples = engine.draw(n=256) self.assertEqual(samples.dtype, dtype) self.assertEqual(samples.device.type, self.device.type) self.assertTrue(torch.all(torch.abs(samples.mean(dim=0) - mean) < 1e-2)) @@ -423,7 +280,7 @@ def test_MultivariateNormalQMCEngineShapiroInvTransform(self): engine = MultivariateNormalQMCEngine( mean=mean, cov=cov, seed=12345, inv_transform=True ) - samples = engine.draw(n=250) + samples = engine.draw(n=256) self.assertEqual(samples.dtype, dtype) self.assertEqual(samples.device.type, self.device.type) self.assertTrue(torch.all(torch.abs(samples.mean(dim=0)) < 1e-2)) @@ -445,7 +302,7 @@ def test_MultivariateNormalQMCEngineShapiroInvTransform(self): engine = MultivariateNormalQMCEngine( mean=mean, cov=cov, seed=12345, inv_transform=True ) - samples = engine.draw(n=250) + samples = engine.draw(n=256) self.assertEqual(samples.dtype, dtype) self.assertEqual(samples.device.type, self.device.type) self.assertTrue(torch.all(torch.abs(samples.mean(dim=0) - mean) < 1e-2)) @@ -469,7 +326,7 @@ def test_MultivariateNormalQMCEngineDegenerate(self): [[1, 0, 1], [0, 1, 1], [1, 1, 2]], device=self.device, dtype=dtype ) engine = MultivariateNormalQMCEngine(mean=mean, cov=cov, seed=12345) - samples = engine.draw(n=2000) + samples = engine.draw(n=4096) self.assertEqual(samples.dtype, dtype) self.assertEqual(samples.device.type, self.device.type) self.assertTrue(torch.all(torch.abs(samples.mean(dim=0)) < 1e-2)) diff --git a/test/utils/test_sampling.py b/test/utils/test_sampling.py index 7fb81bba24..4ad2fc140c 100644 --- a/test/utils/test_sampling.py +++ b/test/utils/test_sampling.py @@ -67,7 +67,7 @@ def test_construct_base_samples(self): with warnings.catch_warnings(record=True) as w, settings.debug(True): construct_base_samples( batch_shape=torch.Size(), - output_shape=torch.Size([200, 6]), + output_shape=torch.Size([2000, 11]), # 200 * 11 = 22000 > 21201 sample_shape=torch.Size([1]), qmc=True, )