diff --git a/.gitignore b/.gitignore index e9e8dc6..4a730d0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,17 @@ # Files +.coverage # Folders +.vscode/ __pycache__/ -docs/build/ -.vscode/ +dist/ +*.egg-info/ +docs/build/ outputs/ data/ tmp/ + +# Version file autogenerated by setuptools_scm +vopy/version.py diff --git a/environment.yml b/environment.yml index 0a68a2d..b1caed5 100644 --- a/environment.yml +++ b/environment.yml @@ -5,13 +5,11 @@ channels: - gpytorch dependencies: - python>=3.10 -- gpytorch - botorch>=0.10.0,<0.12.0 - cvxpy - scikit-learn - scipy - matplotlib -- numpy - jupyter - pytest - pytest-cov @@ -20,6 +18,5 @@ dependencies: - pydocstyle - black - bandit -- sphinx_rtd_theme - pip: - -r docs/requirements.txt diff --git a/pyproject.toml b/pyproject.toml index ffc38e3..2876207 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,39 @@ +[project] +name = "VOPy" +# version = "0.0.1" +dynamic = ["version"] +authors = [ + { name="Y. Cahit Yıldırım", email="cahit.yildirim@bilkent.edu.tr" }, +] +description = "A framework for black-box vector optimization" +readme = "README.md" +license = {file="LICENSE"} +requires-python = ">=3.10" +dependencies = [ + "botorch>=0.10.0,<0.12.0", + "cvxpy", + "scikit-learn", + "scipy", + "matplotlib", +] + +[project.urls] +Homepage = "https://github.com/Bilkent-CYBORG/VOPy" +Documentation = "https://vopy.readthedocs.io/en/latest/" +Issues = "https://github.com/Bilkent-CYBORG/VOPy/issues" + +[build-system] +requires = ["setuptools>=64", "setuptools-scm>=8"] +build-backend = "setuptools.build_meta" + +[tool.setuptools] +packages = ["vopy"] + +[tool.setuptools_scm] +# Should be present even if its empty. +local_scheme = "node-and-date" +write_to = "./vopy/version.py" + [tool.pytest.ini_options] filterwarnings = [ "ignore::UserWarning", diff --git a/requirements.txt b/requirements.txt index 2e3e2ef..b6ec5d0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,3 @@ -gpytorch botorch>=0.10.0,<0.12.0 cvxpy scikit-learn @@ -13,6 +12,5 @@ flake8-print pydocstyle black bandit -sphinx_rtd_theme -r docs/requirements.txt diff --git a/test/models/test_gpytorch.py b/test/models/test_gpytorch.py index 49a0a59..b3eb31f 100644 --- a/test/models/test_gpytorch.py +++ b/test/models/test_gpytorch.py @@ -17,6 +17,8 @@ get_gpytorch_model_w_known_hyperparams, ) +from vopy.utils import set_seed +from vopy.utils.seed import SEED from vopy.maximization_problem import Problem @@ -25,6 +27,7 @@ class TestMultitaskExactGPModel(unittest.TestCase): def setUp(self): """Set up sample data and model for tests.""" + set_seed(SEED) self.X = torch.randn(10, 2) self.Y = torch.randn(10, 2) self.likelihood = MultitaskGaussianLikelihood(num_tasks=self.Y.shape[-1]) @@ -41,6 +44,7 @@ class TestBatchIndependentExactGPModel(unittest.TestCase): def setUp(self): """Set up sample data and model for tests.""" + set_seed(SEED) self.X = torch.randn(10, 2) self.Y = torch.randn(10, 2) self.likelihood = GaussianLikelihood() @@ -70,6 +74,7 @@ class TestGPyTorchMultioutputExactModel(unittest.TestCase): def setUp(self): """Set up model instance with test data.""" # Use the testable subclass to avoid abstract class issues + set_seed(SEED) self.model = TestableGPyTorchMultioutputExactModel( input_dim=2, output_dim=2, noise_var=0.1, model_kind=MultitaskExactGPModel ) @@ -113,6 +118,7 @@ class TestCorrelatedExactGPyTorchModel(unittest.TestCase): def setUp(self): """Set up correlated multitask model.""" + set_seed(SEED) self.model = CorrelatedExactGPyTorchModel(input_dim=2, output_dim=2, noise_var=0.1) self.X = torch.randn(5, 2) self.Y = torch.randn(5, 2) @@ -122,7 +128,12 @@ def setUp(self): def test_predict(self): """Test predict method.""" means, variances = self.model.predict(self.X) - self.assertGreaterEqual(np.min(variances), 0, "Negative variance.") + for i in range(len(self.X)): + with self.subTest(i=i): + try: + np.linalg.cholesky(variances[i].reshape(self.Y.shape[1], self.Y.shape[1])) + except np.linalg.LinAlgError: + self.fail("Covariance matrix is not positive definite.") class TestIndependentExactGPyTorchModel(unittest.TestCase): @@ -130,6 +141,7 @@ class TestIndependentExactGPyTorchModel(unittest.TestCase): def setUp(self): """Set up independent multitask model.""" + set_seed(SEED) self.model = IndependentExactGPyTorchModel(input_dim=2, output_dim=2, noise_var=0.1) self.X = torch.randn(5, 2) self.Y = torch.randn(5, 2) @@ -147,6 +159,8 @@ class TestGetGPyTorchModelWithKnownHyperparams(unittest.TestCase): def test_model_with_given_data(self): """Test if the model is created correctly when X and Y data are provided.""" + set_seed(SEED) + self.input_dim = 2 self.output_dim = 2 self.noise_var = 0.1 @@ -187,6 +201,7 @@ class TestSingleTaskGP(unittest.TestCase): def setUp(self): """Set up single-task GP model.""" + set_seed(SEED) self.X = torch.randn(10, 2) self.Y = torch.randn(10) self.likelihood = GaussianLikelihood() @@ -203,6 +218,7 @@ class TestGPyTorchModelListExactModel(unittest.TestCase): def setUp(self): """Set up multi-output GP model list.""" + set_seed(SEED) self.input_dim = 2 self.output_dim = 2 self.model = GPyTorchModelListExactModel( @@ -246,6 +262,7 @@ class TestGetGPyTorchModelListWithKnownHyperparams(unittest.TestCase): def setUp(self): """Set up problem instance with test data.""" + set_seed(SEED) self.input_dim = 2 self.output_dim = 2 self.noise_var = 0.1