From f4b4c105dce5d26e00f3135fc88e7051c518fe4e Mon Sep 17 00:00:00 2001 From: "da Silva Pereira, Weslley" Date: Mon, 24 Jun 2024 16:01:02 -0600 Subject: [PATCH 01/24] Repository was moved to https://github.com/NREL/bbopt --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index dad03639..b15e551d 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ Surrogate models and active learning for scientific applications. +__This repository was moved to https://github.com/NREL/bbopt__ + ## Building This project uses [pdm](https://pdm-project.org/en/stable/) as its package manager. With pdm installed, run `pdm install` at the root of this repository to install the dependencies. The file [pyproject.toml](pyproject.toml) has the list of dependencies and configurations for the project. Use `pdm build` to build the project. The build artifacts will be in the `dist` directory. Please, find more information about pdm in its website. @@ -20,4 +22,4 @@ Please, read the [contributing guidelines](CONTRIBUTING.md) before contributing ## License -This project is licensed under the GPL-3.0 License. See the [LICENSE](LICENSE) file for details. \ No newline at end of file +This project is licensed under the GPL-3.0 License. See the [LICENSE](LICENSE) file for details. From c2bb6ab74438cfc2c8bed43428c14d0c856c0a93 Mon Sep 17 00:00:00 2001 From: Weslley da Silva Pereira Date: Fri, 21 Jun 2024 14:10:08 -0600 Subject: [PATCH 02/24] Fix problem 26 in GOSAC benchmark --- tests/gosac_benchmark.py | 62 +++++++++++++++++++++++---------------- tests/test_gosac_bench.py | 1 + 2 files changed, 37 insertions(+), 26 deletions(-) diff --git a/tests/gosac_benchmark.py b/tests/gosac_benchmark.py index e4a80595..9ddeb0bc 100644 --- a/tests/gosac_benchmark.py +++ b/tests/gosac_benchmark.py @@ -4,6 +4,38 @@ from typing import Callable, Optional +def fRana(x: np.ndarray) -> np.ndarray: + # Source: http://infinity77.net/global_optimization/test_functions_nd_R.html#go_benchmark.Rana + x1 = x[:, 0] + return np.sum( + x.T + * np.sin(np.sqrt(np.abs(x1 - x.T + 1))) + * np.cos(np.sqrt(np.abs(x1 + x.T + 1))) + + (x1 + 1) + * np.sin(np.sqrt(np.abs(x1 + x.T + 1))) + * np.cos(np.sqrt(np.abs(x1 - x.T + 1))), + axis=0, + ) + + +def fWeierstrass(x: np.ndarray) -> np.ndarray: + # Source: http://infinity77.net/global_optimization/test_functions_nd_W.html#go_benchmark.Weierstrass + n = x.shape[1] + kmax = 20 + a = 0.5 + b = 3 + return np.sum( + sum( + [ + (a**k) * np.cos(2 * np.pi * (b**k) * (x + 0.5)) + for k in range(kmax + 1) + ] + ) + - n * sum([(a**k) * np.cos(np.pi * (b**k)) for k in range(10 + 1)]), + axis=1, + ) + + @dataclass class Problem: """A class to represent a problem for the GOSAC benchmark. @@ -384,19 +416,7 @@ class Problem: + np.exp((1 - np.sin(x[:, 0])) ** 2) * np.cos(x[:, 1]) + np.exp((1 - np.cos(x[:, 1])) ** 2) * np.sin(x[:, 0]), # Rana test function - lambda x: np.reshape( - np.sum( - x.T - * np.sin(np.sqrt(np.abs(x[:, 0] - x.T + 1))) - * np.cos(np.sqrt(np.abs(x[:, 0] + x.T + 1))) - + (x[:, 0] + 1) - * np.sin(np.sqrt(np.abs(x[:, 0] + x.T + 1))) - * np.cos(np.sqrt(np.abs(x[:, 0] - x.T + 1))), - axis=0, - ) - - 5, - (-1, 1), - ), + lambda x: np.reshape(fRana(x) - 5, (-1, 1)), (0,), ((-9, 9), (-3 * np.pi, 3 * np.pi)), (-8, -9.4142), @@ -675,21 +695,11 @@ class Problem: gosac_p.append( Problem( # Weierstrass test function - lambda x: np.sum( - sum( - [ - (2 ** (-k)) * np.cos(2 * np.pi * (3**k) * (x + 0.5)) - for k in range(21) - ] - ) - - 10 - * sum([(2 ** (-k)) * np.cos(np.pi * (3**k)) for k in range(21)]), - axis=1, - ), + fWeierstrass, # Vicent test function lambda x: np.reshape(-np.sum(np.sin(10 * np.log(x)), axis=1), (-1, 1)), - tuple(range(10)), - ((1, 3),) * 10, + (), + ((0.25, np.pi),) * 10, (3, 2, 3, 2, 3, 2, 3, 3, 1, 2), 1.1783, ) diff --git a/tests/test_gosac_bench.py b/tests/test_gosac_bench.py index 12ac853e..3a98a0fc 100644 --- a/tests/test_gosac_bench.py +++ b/tests/test_gosac_bench.py @@ -54,6 +54,7 @@ def test_gosac(problem: gosacbmk.Problem) -> None: @pytest.mark.parametrize("problem", gosacbmk.gosac_p) def test_benchmark(problem: gosacbmk.Problem) -> None: + print(problem.xmin) print(problem.fmin) print(problem.objf(np.asarray([problem.xmin]))[0]) print(problem.gfun(np.asarray([problem.xmin]))[0]) From d940b098fddfbf11867cd572e7fac99d4c8f83d0 Mon Sep 17 00:00:00 2001 From: Weslley da Silva Pereira Date: Fri, 21 Jun 2024 14:58:29 -0600 Subject: [PATCH 03/24] Update copyright information --- blackboxopt/__init__.py | 2 +- blackboxopt/acquisition.py | 2 +- blackboxopt/optimize.py | 2 +- blackboxopt/problem.py | 2 +- blackboxopt/rbf.py | 2 +- blackboxopt/sampling.py | 2 +- examples/multiobj/pareto_front.ipynb | 2 +- examples/multiobj/socemo.ipynb | 2 +- examples/opt_with_constr/example_gosac_1.py | 2 +- examples/opt_with_constr/example_gosac_2.py | 2 +- examples/sampling.ipynb | 2 +- examples/single_obj_rbf/LocalStochRBFstop.py | 2 +- examples/single_obj_rbf/compareLearningStrategies.py | 2 +- examples/single_obj_rbf/data.py | 2 +- examples/single_obj_rbf/datainput_Branin.py | 2 +- examples/single_obj_rbf/datainput_BraninWithInteger.py | 2 +- examples/single_obj_rbf/datainput_hartman3.py | 2 +- examples/single_obj_rbf/datainput_rastrigin.py | 2 +- examples/single_obj_rbf/optprogram1.py | 2 +- examples/vlse_benchmark/vlse_bench.ipynb | 2 +- examples/vlse_benchmark/vlse_bench.py | 2 +- tests/test_optimize.py | 2 +- tests/test_rbf.py | 2 +- tests/test_sampling.py | 2 +- tests/test_vlse_bench.py | 2 +- tests/vlse_benchmark/__init__.py | 2 +- 26 files changed, 26 insertions(+), 26 deletions(-) diff --git a/blackboxopt/__init__.py b/blackboxopt/__init__.py index 0378ad5b..2354a0d6 100644 --- a/blackboxopt/__init__.py +++ b/blackboxopt/__init__.py @@ -1,6 +1,6 @@ """Black-Box Optimization Library""" -# Copyright (C) 2024 National Renewable Energy Laboratory +# Copyright (c) 2024 Alliance for Sustainable Energy, LLC # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/blackboxopt/acquisition.py b/blackboxopt/acquisition.py index a49ff7f3..df1f39f6 100644 --- a/blackboxopt/acquisition.py +++ b/blackboxopt/acquisition.py @@ -1,6 +1,6 @@ """Acquisition functions for surrogate optimization.""" -# Copyright (C) 2024 National Renewable Energy Laboratory +# Copyright (c) 2024 Alliance for Sustainable Energy, LLC # Copyright (C) 2014 Cornell University # This program is free software: you can redistribute it and/or modify diff --git a/blackboxopt/optimize.py b/blackboxopt/optimize.py index 394a5a2e..5fda7cc3 100644 --- a/blackboxopt/optimize.py +++ b/blackboxopt/optimize.py @@ -1,6 +1,6 @@ """Optimization algorithms for blackboxopt.""" -# Copyright (C) 2024 National Renewable Energy Laboratory +# Copyright (c) 2024 Alliance for Sustainable Energy, LLC # Copyright (C) 2014 Cornell University # This program is free software: you can redistribute it and/or modify diff --git a/blackboxopt/problem.py b/blackboxopt/problem.py index ce8abddc..7af2c161 100644 --- a/blackboxopt/problem.py +++ b/blackboxopt/problem.py @@ -1,6 +1,6 @@ """Problem definitions for interfacing with pymoo.""" -# Copyright (C) 2024 National Renewable Energy Laboratory +# Copyright (c) 2024 Alliance for Sustainable Energy, LLC # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/blackboxopt/rbf.py b/blackboxopt/rbf.py index 4444f6f7..3b0c3d33 100644 --- a/blackboxopt/rbf.py +++ b/blackboxopt/rbf.py @@ -1,6 +1,6 @@ """Radial Basis Function model.""" -# Copyright (C) 2024 National Renewable Energy Laboratory +# Copyright (c) 2024 Alliance for Sustainable Energy, LLC # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/blackboxopt/sampling.py b/blackboxopt/sampling.py index 3aa609bf..4cf70884 100644 --- a/blackboxopt/sampling.py +++ b/blackboxopt/sampling.py @@ -1,6 +1,6 @@ """Sampling strategies for the optimization algorithms.""" -# Copyright (C) 2024 National Renewable Energy Laboratory +# Copyright (c) 2024 Alliance for Sustainable Energy, LLC # Copyright (C) 2014 Cornell University # This program is free software: you can redistribute it and/or modify diff --git a/examples/multiobj/pareto_front.ipynb b/examples/multiobj/pareto_front.ipynb index 50a40040..31996ab1 100644 --- a/examples/multiobj/pareto_front.ipynb +++ b/examples/multiobj/pareto_front.ipynb @@ -9,7 +9,7 @@ "\"\"\"Example of finding the pareto front of a set,\n", "and finding target values to fill gaps in the front\"\"\"\n", "\n", - "# Copyright (C) 2024 National Renewable Energy Laboratory\n", + "# Copyright (c) 2024 Alliance for Sustainable Energy, LLC\n", "\n", "# This program is free software: you can redistribute it and/or modify\n", "# it under the terms of the GNU General Public License as published by\n", diff --git a/examples/multiobj/socemo.ipynb b/examples/multiobj/socemo.ipynb index 2e7b05f4..60a7e2a8 100644 --- a/examples/multiobj/socemo.ipynb +++ b/examples/multiobj/socemo.ipynb @@ -8,7 +8,7 @@ "source": [ "\"\"\"Example showing the use of SOCEMO for multi-objective optimization\"\"\"\n", "\n", - "# Copyright (C) 2024 National Renewable Energy Laboratory\n", + "# Copyright (c) 2024 Alliance for Sustainable Energy, LLC\n", "\n", "# This program is free software: you can redistribute it and/or modify\n", "# it under the terms of the GNU General Public License as published by\n", diff --git a/examples/opt_with_constr/example_gosac_1.py b/examples/opt_with_constr/example_gosac_1.py index 1027b1c0..44058cfc 100644 --- a/examples/opt_with_constr/example_gosac_1.py +++ b/examples/opt_with_constr/example_gosac_1.py @@ -1,6 +1,6 @@ """Example of using GOSAC to optimize a function with constraints.""" -# Copyright (C) 2024 National Renewable Energy Laboratory +# Copyright (c) 2024 Alliance for Sustainable Energy, LLC # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/examples/opt_with_constr/example_gosac_2.py b/examples/opt_with_constr/example_gosac_2.py index c375c2e5..d885af95 100644 --- a/examples/opt_with_constr/example_gosac_2.py +++ b/examples/opt_with_constr/example_gosac_2.py @@ -1,6 +1,6 @@ """Example of using GOSAC to optimize a function with constraints.""" -# Copyright (C) 2024 National Renewable Energy Laboratory +# Copyright (c) 2024 Alliance for Sustainable Energy, LLC # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/examples/sampling.ipynb b/examples/sampling.ipynb index 0892d487..ad517c61 100644 --- a/examples/sampling.ipynb +++ b/examples/sampling.ipynb @@ -303,7 +303,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" + "version": "3.9.13" } }, "nbformat": 4, diff --git a/examples/single_obj_rbf/LocalStochRBFstop.py b/examples/single_obj_rbf/LocalStochRBFstop.py index 97379de6..438914e2 100644 --- a/examples/single_obj_rbf/LocalStochRBFstop.py +++ b/examples/single_obj_rbf/LocalStochRBFstop.py @@ -1,6 +1,6 @@ """Simple example for the usage of the minimize function with no restarts.""" -# Copyright (C) 2024 National Renewable Energy Laboratory +# Copyright (c) 2024 Alliance for Sustainable Energy, LLC # Copyright (C) 2013 Cornell University # This program is free software: you can redistribute it and/or modify diff --git a/examples/single_obj_rbf/compareLearningStrategies.py b/examples/single_obj_rbf/compareLearningStrategies.py index 2f51405f..ad56558a 100644 --- a/examples/single_obj_rbf/compareLearningStrategies.py +++ b/examples/single_obj_rbf/compareLearningStrategies.py @@ -1,6 +1,6 @@ """Compare different learning strategies for RBF surrogate optimization.""" -# Copyright (C) 2024 National Renewable Energy Laboratory +# Copyright (c) 2024 Alliance for Sustainable Energy, LLC # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/examples/single_obj_rbf/data.py b/examples/single_obj_rbf/data.py index 28be1b8c..a707a82e 100644 --- a/examples/single_obj_rbf/data.py +++ b/examples/single_obj_rbf/data.py @@ -1,6 +1,6 @@ """Data class for the problem definition.""" -# Copyright (C) 2024 National Renewable Energy Laboratory +# Copyright (c) 2024 Alliance for Sustainable Energy, LLC # Copyright (C) 2013 Cornell University # This program is free software: you can redistribute it and/or modify diff --git a/examples/single_obj_rbf/datainput_Branin.py b/examples/single_obj_rbf/datainput_Branin.py index 681c8047..52465f70 100644 --- a/examples/single_obj_rbf/datainput_Branin.py +++ b/examples/single_obj_rbf/datainput_Branin.py @@ -1,6 +1,6 @@ """Data class for the Branin problem definition.""" -# Copyright (C) 2024 National Renewable Energy Laboratory +# Copyright (c) 2024 Alliance for Sustainable Energy, LLC # Copyright (C) 2013 Cornell University # This program is free software: you can redistribute it and/or modify diff --git a/examples/single_obj_rbf/datainput_BraninWithInteger.py b/examples/single_obj_rbf/datainput_BraninWithInteger.py index 8e1917bd..a8e95669 100644 --- a/examples/single_obj_rbf/datainput_BraninWithInteger.py +++ b/examples/single_obj_rbf/datainput_BraninWithInteger.py @@ -1,6 +1,6 @@ """Data class for the Branin problem definition.""" -# Copyright (C) 2024 National Renewable Energy Laboratory +# Copyright (c) 2024 Alliance for Sustainable Energy, LLC # Copyright (C) 2013 Cornell University # This program is free software: you can redistribute it and/or modify diff --git a/examples/single_obj_rbf/datainput_hartman3.py b/examples/single_obj_rbf/datainput_hartman3.py index 33c5b05f..bcfbd69a 100644 --- a/examples/single_obj_rbf/datainput_hartman3.py +++ b/examples/single_obj_rbf/datainput_hartman3.py @@ -1,6 +1,6 @@ """Data class for the Hartman3 problem definition.""" -# Copyright (C) 2024 National Renewable Energy Laboratory +# Copyright (c) 2024 Alliance for Sustainable Energy, LLC # Copyright (C) 2013 Cornell University # This program is free software: you can redistribute it and/or modify diff --git a/examples/single_obj_rbf/datainput_rastrigin.py b/examples/single_obj_rbf/datainput_rastrigin.py index 38a723cc..d412a77b 100644 --- a/examples/single_obj_rbf/datainput_rastrigin.py +++ b/examples/single_obj_rbf/datainput_rastrigin.py @@ -1,6 +1,6 @@ """Data class for the Rastigrin problem definition.""" -# Copyright (C) 2024 National Renewable Energy Laboratory +# Copyright (c) 2024 Alliance for Sustainable Energy, LLC # Copyright (C) 2014 Cornell University # This program is free software: you can redistribute it and/or modify diff --git a/examples/single_obj_rbf/optprogram1.py b/examples/single_obj_rbf/optprogram1.py index 4ac5c2ad..f4cff768 100644 --- a/examples/single_obj_rbf/optprogram1.py +++ b/examples/single_obj_rbf/optprogram1.py @@ -1,6 +1,6 @@ """Example with optimization and plot.""" -# Copyright (C) 2024 National Renewable Energy Laboratory +# Copyright (c) 2024 Alliance for Sustainable Energy, LLC # Copyright (C) 2014 Cornell University # This program is free software: you can redistribute it and/or modify diff --git a/examples/vlse_benchmark/vlse_bench.ipynb b/examples/vlse_benchmark/vlse_bench.ipynb index 454a0546..079a2434 100644 --- a/examples/vlse_benchmark/vlse_bench.ipynb +++ b/examples/vlse_benchmark/vlse_bench.ipynb @@ -8,7 +8,7 @@ "source": [ "\"\"\"Show the results of the optimization on the VLSE benchmark.\"\"\"\n", "\n", - "# Copyright (C) 2024 National Renewable Energy Laboratory\n", + "# Copyright (c) 2024 Alliance for Sustainable Energy, LLC\n", "\n", "# This program is free software: you can redistribute it and/or modify\n", "# it under the terms of the GNU General Public License as published by\n", diff --git a/examples/vlse_benchmark/vlse_bench.py b/examples/vlse_benchmark/vlse_bench.py index c9d78241..49751649 100644 --- a/examples/vlse_benchmark/vlse_bench.py +++ b/examples/vlse_benchmark/vlse_bench.py @@ -1,6 +1,6 @@ """Run the optimization on the VLSE benchmark.""" -# Copyright (C) 2024 National Renewable Energy Laboratory +# Copyright (c) 2024 Alliance for Sustainable Energy, LLC # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/tests/test_optimize.py b/tests/test_optimize.py index 65655d36..25cf5db2 100644 --- a/tests/test_optimize.py +++ b/tests/test_optimize.py @@ -1,6 +1,6 @@ """Test the optimization routines.""" -# Copyright (C) 2024 National Renewable Energy Laboratory +# Copyright (c) 2024 Alliance for Sustainable Energy, LLC # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/tests/test_rbf.py b/tests/test_rbf.py index cdf8c764..4a29c7ee 100644 --- a/tests/test_rbf.py +++ b/tests/test_rbf.py @@ -1,6 +1,6 @@ """Test the RBF model.""" -# Copyright (C) 2024 National Renewable Energy Laboratory +# Copyright (c) 2024 Alliance for Sustainable Energy, LLC # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/tests/test_sampling.py b/tests/test_sampling.py index 995d368b..53962328 100644 --- a/tests/test_sampling.py +++ b/tests/test_sampling.py @@ -1,6 +1,6 @@ """Test the sampling functions.""" -# Copyright (C) 2024 National Renewable Energy Laboratory +# Copyright (c) 2024 Alliance for Sustainable Energy, LLC # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/tests/test_vlse_bench.py b/tests/test_vlse_bench.py index bee4d875..e759ba6b 100644 --- a/tests/test_vlse_bench.py +++ b/tests/test_vlse_bench.py @@ -1,6 +1,6 @@ """Test functions from the VLSE benchmark.""" -# Copyright (C) 2024 National Renewable Energy Laboratory +# Copyright (c) 2024 Alliance for Sustainable Energy, LLC # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/tests/vlse_benchmark/__init__.py b/tests/vlse_benchmark/__init__.py index 4477dca2..733d72ce 100644 --- a/tests/vlse_benchmark/__init__.py +++ b/tests/vlse_benchmark/__init__.py @@ -1,6 +1,6 @@ """Python interface to the Virtual Library of Simulation Experiments.""" -# Copyright (C) 2024 National Renewable Energy Laboratory +# Copyright (c) 2024 Alliance for Sustainable Energy, LLC # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by From 1ba9f5fcb1b5ba7c353d893d2a2387fc8dd11ec3 Mon Sep 17 00:00:00 2001 From: Weslley da Silva Pereira Date: Fri, 21 Jun 2024 16:05:10 -0600 Subject: [PATCH 04/24] Update to version 0.4.0 --- README.md | 4 ++++ blackboxopt/__init__.py | 2 +- blackboxopt/acquisition.py | 2 +- blackboxopt/optimize.py | 2 +- blackboxopt/problem.py | 2 +- blackboxopt/rbf.py | 2 +- blackboxopt/sampling.py | 2 +- docs/conf.py | 4 ++-- examples/multiobj/pareto_front.ipynb | 2 +- examples/multiobj/socemo.ipynb | 2 +- examples/opt_with_constr/example_gosac_1.py | 2 +- examples/opt_with_constr/example_gosac_2.py | 2 +- examples/sampling.ipynb | 4 ++-- examples/single_obj_rbf/LocalStochRBFstop.py | 2 +- examples/single_obj_rbf/compareLearningStrategies.py | 2 +- examples/single_obj_rbf/data.py | 2 +- examples/single_obj_rbf/datainput_Branin.py | 2 +- examples/single_obj_rbf/datainput_BraninWithInteger.py | 2 +- examples/single_obj_rbf/datainput_hartman3.py | 2 +- examples/single_obj_rbf/datainput_rastrigin.py | 2 +- examples/single_obj_rbf/optprogram1.py | 2 +- examples/vlse_benchmark/vlse_bench.ipynb | 2 +- examples/vlse_benchmark/vlse_bench.py | 2 +- pyproject.toml | 2 +- tests/test_optimize.py | 2 +- tests/test_rbf.py | 2 +- tests/test_sampling.py | 2 +- tests/test_vlse_bench.py | 2 +- tests/vlse_benchmark/__init__.py | 2 +- 29 files changed, 34 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index b15e551d..32cdbd3f 100644 --- a/README.md +++ b/README.md @@ -23,3 +23,7 @@ Please, read the [contributing guidelines](CONTRIBUTING.md) before contributing ## License This project is licensed under the GPL-3.0 License. See the [LICENSE](LICENSE) file for details. + +--- + +_NREL Software Record number: SWR-24-57_ diff --git a/blackboxopt/__init__.py b/blackboxopt/__init__.py index 2354a0d6..34862248 100644 --- a/blackboxopt/__init__.py +++ b/blackboxopt/__init__.py @@ -16,7 +16,7 @@ # along with this program. If not, see . __all__ = ["acquisition", "optimize", "sampling", "rbf"] -__version__ = "0.3.3" +__version__ = "0.4.0" from . import acquisition from . import optimize diff --git a/blackboxopt/acquisition.py b/blackboxopt/acquisition.py index df1f39f6..72eb8497 100644 --- a/blackboxopt/acquisition.py +++ b/blackboxopt/acquisition.py @@ -31,7 +31,7 @@ "Haoyu Jia", "Weslley S. Pereira", ] -__version__ = "0.3.3" +__version__ = "0.4.0" __deprecated__ = False import numpy as np diff --git a/blackboxopt/optimize.py b/blackboxopt/optimize.py index 5fda7cc3..eda6da21 100644 --- a/blackboxopt/optimize.py +++ b/blackboxopt/optimize.py @@ -31,7 +31,7 @@ "Haoyu Jia", "Weslley S. Pereira", ] -__version__ = "0.3.3" +__version__ = "0.4.0" __deprecated__ = False from typing import Callable, Optional, Union diff --git a/blackboxopt/problem.py b/blackboxopt/problem.py index 7af2c161..1b2bb7ac 100644 --- a/blackboxopt/problem.py +++ b/blackboxopt/problem.py @@ -20,7 +20,7 @@ __maintainer__ = "Weslley S. Pereira" __email__ = "weslley.dasilvapereira@nrel.gov" __credits__ = ["Weslley S. Pereira"] -__version__ = "0.3.3" +__version__ = "0.4.0" __deprecated__ = False import numpy as np diff --git a/blackboxopt/rbf.py b/blackboxopt/rbf.py index 3b0c3d33..870e39df 100644 --- a/blackboxopt/rbf.py +++ b/blackboxopt/rbf.py @@ -20,7 +20,7 @@ __maintainer__ = "Weslley S. Pereira" __email__ = "weslley.dasilvapereira@nrel.gov" __credits__ = ["Weslley S. Pereira"] -__version__ = "0.3.3" +__version__ = "0.4.0" __deprecated__ = False from typing import Optional diff --git a/blackboxopt/sampling.py b/blackboxopt/sampling.py index 4cf70884..e0119e51 100644 --- a/blackboxopt/sampling.py +++ b/blackboxopt/sampling.py @@ -31,7 +31,7 @@ "Haoyu Jia", "Weslley S. Pereira", ] -__version__ = "0.3.3" +__version__ = "0.4.0" __deprecated__ = False import numpy as np diff --git a/docs/conf.py b/docs/conf.py index 346e96f5..217d4316 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -15,9 +15,9 @@ # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information project = "Black-box Opt" -copyright = "2024, National Renewable Energy Laboratory" +copyright = "2024, Alliance for Sustainable Energy, LLC" author = "Weslley S. Pereira" -release = "0.3.3" +release = "0.4.0" # -- General configuration --------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration diff --git a/examples/multiobj/pareto_front.ipynb b/examples/multiobj/pareto_front.ipynb index 31996ab1..2a8cbf0b 100644 --- a/examples/multiobj/pareto_front.ipynb +++ b/examples/multiobj/pareto_front.ipynb @@ -29,7 +29,7 @@ "__maintainer__ = \"Weslley S. Pereira\"\n", "__email__ = \"weslley.dasilvapereira@nrel.gov\"\n", "__credits__ = [\"Weslley S. Pereira\"]\n", - "__version__ = \"0.3.3\"\n", + "__version__ = \"0.4.0\"\n", "__deprecated__ = False" ] }, diff --git a/examples/multiobj/socemo.ipynb b/examples/multiobj/socemo.ipynb index 60a7e2a8..f474c403 100644 --- a/examples/multiobj/socemo.ipynb +++ b/examples/multiobj/socemo.ipynb @@ -28,7 +28,7 @@ "__maintainer__ = \"Weslley S. Pereira\"\n", "__email__ = \"weslley.dasilvapereira@nrel.gov\"\n", "__credits__ = [\"Weslley S. Pereira\"]\n", - "__version__ = \"0.3.3\"\n", + "__version__ = \"0.4.0\"\n", "__deprecated__ = False" ] }, diff --git a/examples/opt_with_constr/example_gosac_1.py b/examples/opt_with_constr/example_gosac_1.py index 44058cfc..6b4d9fcb 100644 --- a/examples/opt_with_constr/example_gosac_1.py +++ b/examples/opt_with_constr/example_gosac_1.py @@ -20,7 +20,7 @@ __maintainer__ = "Weslley S. Pereira" __email__ = "weslley.dasilvapereira@nrel.gov" __credits__ = ["Juliane Mueller", "Weslley S. Pereira"] -__version__ = "0.3.3" +__version__ = "0.4.0" __deprecated__ = False from blackboxopt.optimize import gosac diff --git a/examples/opt_with_constr/example_gosac_2.py b/examples/opt_with_constr/example_gosac_2.py index d885af95..22ae1f6a 100644 --- a/examples/opt_with_constr/example_gosac_2.py +++ b/examples/opt_with_constr/example_gosac_2.py @@ -20,7 +20,7 @@ __maintainer__ = "Weslley S. Pereira" __email__ = "weslley.dasilvapereira@nrel.gov" __credits__ = ["Juliane Mueller", "Weslley S. Pereira"] -__version__ = "0.3.3" +__version__ = "0.4.0" __deprecated__ = False from blackboxopt.optimize import gosac diff --git a/examples/sampling.ipynb b/examples/sampling.ipynb index ad517c61..f954138c 100644 --- a/examples/sampling.ipynb +++ b/examples/sampling.ipynb @@ -8,7 +8,7 @@ "source": [ "\"\"\"Example showing different sampling strategies\"\"\"\n", "\n", - "# Copyright (C) 2024 National Renewable Energy Laboratory\n", + "# Copyright (c) 2024 Alliance for Sustainable Energy, LLC\n", "\n", "# This program is free software: you can redistribute it and/or modify\n", "# it under the terms of the GNU General Public License as published by\n", @@ -28,7 +28,7 @@ "__maintainer__ = \"Weslley S. Pereira\"\n", "__email__ = \"weslley.dasilvapereira@nrel.gov\"\n", "__credits__ = [\"Weslley S. Pereira\"]\n", - "__version__ = \"0.3.3\"\n", + "__version__ = \"0.4.0\"\n", "__deprecated__ = False" ] }, diff --git a/examples/single_obj_rbf/LocalStochRBFstop.py b/examples/single_obj_rbf/LocalStochRBFstop.py index 438914e2..d6d3fde0 100644 --- a/examples/single_obj_rbf/LocalStochRBFstop.py +++ b/examples/single_obj_rbf/LocalStochRBFstop.py @@ -26,7 +26,7 @@ "Haoyu Jia", "Weslley S. Pereira", ] -__version__ = "0.3.3" +__version__ = "0.4.0" __deprecated__ = False from optprogram1 import read_check_data_file diff --git a/examples/single_obj_rbf/compareLearningStrategies.py b/examples/single_obj_rbf/compareLearningStrategies.py index ad56558a..7177b694 100644 --- a/examples/single_obj_rbf/compareLearningStrategies.py +++ b/examples/single_obj_rbf/compareLearningStrategies.py @@ -20,7 +20,7 @@ __maintainer__ = "Weslley S. Pereira" __email__ = "weslley.dasilvapereira@nrel.gov" __credits__ = ["Weslley S. Pereira"] -__version__ = "0.3.3" +__version__ = "0.4.0" __deprecated__ = False diff --git a/examples/single_obj_rbf/data.py b/examples/single_obj_rbf/data.py index a707a82e..6da3f00b 100644 --- a/examples/single_obj_rbf/data.py +++ b/examples/single_obj_rbf/data.py @@ -26,7 +26,7 @@ "Haoyu Jia", "Weslley S. Pereira", ] -__version__ = "0.3.3" +__version__ = "0.4.0" __deprecated__ = False from dataclasses import dataclass diff --git a/examples/single_obj_rbf/datainput_Branin.py b/examples/single_obj_rbf/datainput_Branin.py index 52465f70..5ad5bf4b 100644 --- a/examples/single_obj_rbf/datainput_Branin.py +++ b/examples/single_obj_rbf/datainput_Branin.py @@ -26,7 +26,7 @@ "Haoyu Jia", "Weslley S. Pereira", ] -__version__ = "0.3.3" +__version__ = "0.4.0" __deprecated__ = False import numpy as np diff --git a/examples/single_obj_rbf/datainput_BraninWithInteger.py b/examples/single_obj_rbf/datainput_BraninWithInteger.py index a8e95669..0eec7319 100644 --- a/examples/single_obj_rbf/datainput_BraninWithInteger.py +++ b/examples/single_obj_rbf/datainput_BraninWithInteger.py @@ -26,7 +26,7 @@ "Haoyu Jia", "Weslley S. Pereira", ] -__version__ = "0.3.3" +__version__ = "0.4.0" __deprecated__ = False import numpy as np diff --git a/examples/single_obj_rbf/datainput_hartman3.py b/examples/single_obj_rbf/datainput_hartman3.py index bcfbd69a..d2c810c0 100644 --- a/examples/single_obj_rbf/datainput_hartman3.py +++ b/examples/single_obj_rbf/datainput_hartman3.py @@ -26,7 +26,7 @@ "Haoyu Jia", "Weslley S. Pereira", ] -__version__ = "0.3.3" +__version__ = "0.4.0" __deprecated__ = False import numpy as np diff --git a/examples/single_obj_rbf/datainput_rastrigin.py b/examples/single_obj_rbf/datainput_rastrigin.py index d412a77b..2757e68c 100644 --- a/examples/single_obj_rbf/datainput_rastrigin.py +++ b/examples/single_obj_rbf/datainput_rastrigin.py @@ -26,7 +26,7 @@ "Haoyu Jia", "Weslley S. Pereira", ] -__version__ = "0.3.3" +__version__ = "0.4.0" __deprecated__ = False import numpy as np diff --git a/examples/single_obj_rbf/optprogram1.py b/examples/single_obj_rbf/optprogram1.py index f4cff768..3bfa7a94 100644 --- a/examples/single_obj_rbf/optprogram1.py +++ b/examples/single_obj_rbf/optprogram1.py @@ -31,7 +31,7 @@ "Haoyu Jia", "Weslley S. Pereira", ] -__version__ = "0.3.3" +__version__ = "0.4.0" __deprecated__ = False diff --git a/examples/vlse_benchmark/vlse_bench.ipynb b/examples/vlse_benchmark/vlse_bench.ipynb index 079a2434..56918339 100644 --- a/examples/vlse_benchmark/vlse_bench.ipynb +++ b/examples/vlse_benchmark/vlse_bench.ipynb @@ -28,7 +28,7 @@ "__maintainer__ = \"Weslley S. Pereira\"\n", "__email__ = \"weslley.dasilvapereira@nrel.gov\"\n", "__credits__ = [\"Weslley S. Pereira\"]\n", - "__version__ = \"0.3.3\"\n", + "__version__ = \"0.4.0\"\n", "__deprecated__ = False" ] }, diff --git a/examples/vlse_benchmark/vlse_bench.py b/examples/vlse_benchmark/vlse_bench.py index 49751649..ed5393b2 100644 --- a/examples/vlse_benchmark/vlse_bench.py +++ b/examples/vlse_benchmark/vlse_bench.py @@ -20,7 +20,7 @@ __maintainer__ = "Weslley S. Pereira" __email__ = "weslley.dasilvapereira@nrel.gov" __credits__ = ["Weslley S. Pereira"] -__version__ = "0.3.3" +__version__ = "0.4.0" __deprecated__ = False import os diff --git a/pyproject.toml b/pyproject.toml index a1eeebbf..e46b2389 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "blackboxopt" -version = "0.3.3" +version = "0.4.0" description = "Surrogate models and active learning for scientific applications" authors = [ {name = "Weslley da Silva Pereira", email = "weslley.dasilvapereira@nrel.gov"}, diff --git a/tests/test_optimize.py b/tests/test_optimize.py index 25cf5db2..1e44cae7 100644 --- a/tests/test_optimize.py +++ b/tests/test_optimize.py @@ -20,7 +20,7 @@ __maintainer__ = "Weslley S. Pereira" __email__ = "weslley.dasilvapereira@nrel.gov" __credits__ = ["Weslley S. Pereira"] -__version__ = "0.3.3" +__version__ = "0.4.0" __deprecated__ = False import numpy as np diff --git a/tests/test_rbf.py b/tests/test_rbf.py index 4a29c7ee..1598080b 100644 --- a/tests/test_rbf.py +++ b/tests/test_rbf.py @@ -20,7 +20,7 @@ __maintainer__ = "Weslley S. Pereira" __email__ = "weslley.dasilvapereira@nrel.gov" __credits__ = ["Weslley S. Pereira"] -__version__ = "0.3.3" +__version__ = "0.4.0" __deprecated__ = False import numpy as np diff --git a/tests/test_sampling.py b/tests/test_sampling.py index 53962328..dc84d258 100644 --- a/tests/test_sampling.py +++ b/tests/test_sampling.py @@ -20,7 +20,7 @@ __maintainer__ = "Weslley S. Pereira" __email__ = "weslley.dasilvapereira@nrel.gov" __credits__ = ["Weslley S. Pereira"] -__version__ = "0.3.3" +__version__ = "0.4.0" __deprecated__ = False import numpy as np diff --git a/tests/test_vlse_bench.py b/tests/test_vlse_bench.py index e759ba6b..0ea36933 100644 --- a/tests/test_vlse_bench.py +++ b/tests/test_vlse_bench.py @@ -20,7 +20,7 @@ __maintainer__ = "Weslley S. Pereira" __email__ = "weslley.dasilvapereira@nrel.gov" __credits__ = ["Weslley S. Pereira"] -__version__ = "0.3.3" +__version__ = "0.4.0" __deprecated__ = False from copy import deepcopy diff --git a/tests/vlse_benchmark/__init__.py b/tests/vlse_benchmark/__init__.py index 733d72ce..e7910b12 100644 --- a/tests/vlse_benchmark/__init__.py +++ b/tests/vlse_benchmark/__init__.py @@ -27,7 +27,7 @@ __maintainer__ = "Weslley S. Pereira" __email__ = "weslley.dasilvapereira@nrel.gov" __credits__ = ["Sonja Surjanovic", "Derek Bingham", "Weslley S. Pereira"] -__version__ = "0.3.3" +__version__ = "0.4.0" __deprecated__ = False from rpy2.robjects import r From 56a11fdbd7ea757ba4d85498a630e31bac03f31b Mon Sep 17 00:00:00 2001 From: Weslley da Silva Pereira Date: Mon, 24 Jun 2024 08:58:32 -0600 Subject: [PATCH 05/24] Update documentation and license --- LICENSE | 2 ++ docs/requirements.txt | 1 + docs/tests.rst | 26 +++++++++++++++++++++++++- docs/tests.vlse_benchmark.rst | 2 +- 4 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 docs/requirements.txt diff --git a/LICENSE b/LICENSE index f288702d..67a27f98 100644 --- a/LICENSE +++ b/LICENSE @@ -1,3 +1,5 @@ +Copyright (c) 2024 Alliance for Sustainable Energy, LLC + GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 00000000..4170c03e --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1 @@ +sphinx-rtd-theme \ No newline at end of file diff --git a/docs/tests.rst b/docs/tests.rst index 3472b647..640d1103 100644 --- a/docs/tests.rst +++ b/docs/tests.rst @@ -12,6 +12,30 @@ Subpackages Submodules ---------- +tests.gosac\_benchmark module +----------------------------- + +.. automodule:: tests.gosac_benchmark + :members: + :undoc-members: + :show-inheritance: + +tests.test\_gosac\_bench module +------------------------------- + +.. automodule:: tests.test_gosac_bench + :members: + :undoc-members: + :show-inheritance: + +tests.test\_optimize module +--------------------------- + +.. automodule:: tests.test_optimize + :members: + :undoc-members: + :show-inheritance: + tests.test\_rbf module ---------------------- @@ -29,7 +53,7 @@ tests.test\_sampling module :show-inheritance: tests.test\_vlse\_bench module ----------------------------------- +------------------------------ .. automodule:: tests.test_vlse_bench :members: diff --git a/docs/tests.vlse_benchmark.rst b/docs/tests.vlse_benchmark.rst index 2658f736..f829f38a 100644 --- a/docs/tests.vlse_benchmark.rst +++ b/docs/tests.vlse_benchmark.rst @@ -1,5 +1,5 @@ tests.vlse\_benchmark package -================================= +============================= Module contents --------------- From f57e986ae0f49b95649da063e19b402986aaa4df Mon Sep 17 00:00:00 2001 From: "Weslley S. Pereira" Date: Mon, 24 Jun 2024 09:01:20 -0600 Subject: [PATCH 06/24] Create gh-pages.yml --- .github/workflows/gh-pages.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 .github/workflows/gh-pages.yml diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml new file mode 100644 index 00000000..dfb7d62d --- /dev/null +++ b/.github/workflows/gh-pages.yml @@ -0,0 +1,18 @@ +name: Deploy Sphinx documentation to Pages + +on: + push: + branches: [master] # branch to trigger deployment + +jobs: + pages: + runs-on: ubuntu-20.04 + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + permissions: + pages: write + id-token: write + steps: + - id: deployment + uses: sphinx-notes/pages@v3 From 7f9947534ad9a3abf71fa0f433f482d941d2d5a9 Mon Sep 17 00:00:00 2001 From: Weslley da Silva Pereira Date: Mon, 24 Jun 2024 09:04:20 -0600 Subject: [PATCH 07/24] Push to test gh-pages --- pyproject.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index e46b2389..71b7d7d8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,7 +35,6 @@ lint = [ doc = [ "sphinx>=7.2.6", "sphinx-rtd-theme>=2.0.0", - "myst-parser>=2.0.0", ] [tool.pdm.build] From 0106e279e378d04bba0543516837d4d1e7010d89 Mon Sep 17 00:00:00 2001 From: "Weslley S. Pereira" Date: Mon, 24 Jun 2024 09:04:57 -0600 Subject: [PATCH 08/24] Update gh-pages.yml --- .github/workflows/gh-pages.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml index dfb7d62d..d8498e6a 100644 --- a/.github/workflows/gh-pages.yml +++ b/.github/workflows/gh-pages.yml @@ -2,7 +2,7 @@ name: Deploy Sphinx documentation to Pages on: push: - branches: [master] # branch to trigger deployment + branches: [main] # branch to trigger deployment jobs: pages: From fee9e5be763d9e82406493b8223d4cd54c3d35ba Mon Sep 17 00:00:00 2001 From: Weslley da Silva Pereira Date: Mon, 24 Jun 2024 09:22:42 -0600 Subject: [PATCH 09/24] Limit version of numpy because of pymoo --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 71b7d7d8..29740c7c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,7 +9,7 @@ license = {file = "LICENSE"} readme = "README.md" requires-python = ">=3.9" dependencies = [ - "numpy>=1.26.2", + "numpy>=1.26.2,<2.0.0", "scipy>=1.11.4", "pymoo>=0.6.1.1", ] From 5dfe6890461bbd2e625aee0a6b94498c1ff8ddf8 Mon Sep 17 00:00:00 2001 From: Weslley da Silva Pereira Date: Mon, 24 Jun 2024 09:33:47 -0600 Subject: [PATCH 10/24] Adds more requirements to the sphinx docs --- docs/requirements.txt | 5 ++++- pyproject.toml | 8 +++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index 4170c03e..86ee7b16 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1 +1,4 @@ -sphinx-rtd-theme \ No newline at end of file +sphinx +sphinx-rtd-theme +pytest +rpy2 \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 29740c7c..a23b1f50 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -25,9 +25,6 @@ distribution = true test = [ "pytest>=7.4.3", "rpy2==3.5.1", - "matplotlib>=3.8.2", - "snakeviz>=2.2.0", - "jupyter>=1.0.0", ] lint = [ "ruff>=0.3.5", @@ -36,6 +33,11 @@ doc = [ "sphinx>=7.2.6", "sphinx-rtd-theme>=2.0.0", ] +example = [ + "jupyter>=1.0.0", + "matplotlib>=3.8.2", + "snakeviz>=2.2.0", +] [tool.pdm.build] includes = ["blackboxopt/*.py"] From 7476f7dc82a5d406d485be146100a027f9c5f3cb Mon Sep 17 00:00:00 2001 From: Weslley da Silva Pereira Date: Mon, 24 Jun 2024 09:37:10 -0600 Subject: [PATCH 11/24] Move pages to https://nrel.github.io/bbopt --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 32cdbd3f..5104c463 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ This project uses [pdm](https://pdm-project.org/en/stable/) as its package manag ## Documentation -This project uses [Sphinx](https://www.sphinx-doc.org/en/master/) to generate the documentation. The latest documentation is available at https://pages.github.nrel.gov/wdasilv/Black-box-Opt/. To generate the documentation locally, run `make html` in the `docs` directory. The homepage of the documentation is `docs/_build/html/index.html`. +This project uses [Sphinx](https://www.sphinx-doc.org/en/master/) to generate the documentation. The latest documentation is available at https://nrel.github.io/bbopt. To generate the documentation locally, run `make html` in the `docs` directory. The homepage of the documentation is `docs/_build/html/index.html`. ## Testing From 9d43fd70dd90ae418bb034a2ac45940829414b10 Mon Sep 17 00:00:00 2001 From: Weslley da Silva Pereira Date: Mon, 24 Jun 2024 12:24:28 -0600 Subject: [PATCH 12/24] Update to v0.4.1 --- blackboxopt/__init__.py | 2 +- blackboxopt/acquisition.py | 2 +- blackboxopt/optimize.py | 2 +- blackboxopt/problem.py | 2 +- blackboxopt/rbf.py | 2 +- blackboxopt/sampling.py | 2 +- docs/conf.py | 2 +- examples/multiobj/pareto_front.ipynb | 2 +- examples/multiobj/socemo.ipynb | 2 +- examples/opt_with_constr/example_gosac_1.py | 2 +- examples/opt_with_constr/example_gosac_2.py | 2 +- examples/sampling.ipynb | 2 +- examples/single_obj_rbf/LocalStochRBFstop.py | 2 +- examples/single_obj_rbf/compareLearningStrategies.py | 2 +- examples/single_obj_rbf/data.py | 2 +- examples/single_obj_rbf/datainput_Branin.py | 2 +- examples/single_obj_rbf/datainput_BraninWithInteger.py | 2 +- examples/single_obj_rbf/datainput_hartman3.py | 2 +- examples/single_obj_rbf/datainput_rastrigin.py | 2 +- examples/single_obj_rbf/optprogram1.py | 2 +- examples/vlse_benchmark/vlse_bench.ipynb | 2 +- examples/vlse_benchmark/vlse_bench.py | 2 +- pyproject.toml | 2 +- tests/test_optimize.py | 2 +- tests/test_rbf.py | 2 +- tests/test_sampling.py | 2 +- tests/test_vlse_bench.py | 2 +- tests/vlse_benchmark/__init__.py | 2 +- 28 files changed, 28 insertions(+), 28 deletions(-) diff --git a/blackboxopt/__init__.py b/blackboxopt/__init__.py index 34862248..7c2e8fbc 100644 --- a/blackboxopt/__init__.py +++ b/blackboxopt/__init__.py @@ -16,7 +16,7 @@ # along with this program. If not, see . __all__ = ["acquisition", "optimize", "sampling", "rbf"] -__version__ = "0.4.0" +__version__ = "0.4.1" from . import acquisition from . import optimize diff --git a/blackboxopt/acquisition.py b/blackboxopt/acquisition.py index 72eb8497..1c67100e 100644 --- a/blackboxopt/acquisition.py +++ b/blackboxopt/acquisition.py @@ -31,7 +31,7 @@ "Haoyu Jia", "Weslley S. Pereira", ] -__version__ = "0.4.0" +__version__ = "0.4.1" __deprecated__ = False import numpy as np diff --git a/blackboxopt/optimize.py b/blackboxopt/optimize.py index eda6da21..74dadd63 100644 --- a/blackboxopt/optimize.py +++ b/blackboxopt/optimize.py @@ -31,7 +31,7 @@ "Haoyu Jia", "Weslley S. Pereira", ] -__version__ = "0.4.0" +__version__ = "0.4.1" __deprecated__ = False from typing import Callable, Optional, Union diff --git a/blackboxopt/problem.py b/blackboxopt/problem.py index 1b2bb7ac..1568073a 100644 --- a/blackboxopt/problem.py +++ b/blackboxopt/problem.py @@ -20,7 +20,7 @@ __maintainer__ = "Weslley S. Pereira" __email__ = "weslley.dasilvapereira@nrel.gov" __credits__ = ["Weslley S. Pereira"] -__version__ = "0.4.0" +__version__ = "0.4.1" __deprecated__ = False import numpy as np diff --git a/blackboxopt/rbf.py b/blackboxopt/rbf.py index 870e39df..c9d2f504 100644 --- a/blackboxopt/rbf.py +++ b/blackboxopt/rbf.py @@ -20,7 +20,7 @@ __maintainer__ = "Weslley S. Pereira" __email__ = "weslley.dasilvapereira@nrel.gov" __credits__ = ["Weslley S. Pereira"] -__version__ = "0.4.0" +__version__ = "0.4.1" __deprecated__ = False from typing import Optional diff --git a/blackboxopt/sampling.py b/blackboxopt/sampling.py index e0119e51..a99620b9 100644 --- a/blackboxopt/sampling.py +++ b/blackboxopt/sampling.py @@ -31,7 +31,7 @@ "Haoyu Jia", "Weslley S. Pereira", ] -__version__ = "0.4.0" +__version__ = "0.4.1" __deprecated__ = False import numpy as np diff --git a/docs/conf.py b/docs/conf.py index 217d4316..01b8b128 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -17,7 +17,7 @@ project = "Black-box Opt" copyright = "2024, Alliance for Sustainable Energy, LLC" author = "Weslley S. Pereira" -release = "0.4.0" +release = "0.4.1" # -- General configuration --------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration diff --git a/examples/multiobj/pareto_front.ipynb b/examples/multiobj/pareto_front.ipynb index 2a8cbf0b..56159921 100644 --- a/examples/multiobj/pareto_front.ipynb +++ b/examples/multiobj/pareto_front.ipynb @@ -29,7 +29,7 @@ "__maintainer__ = \"Weslley S. Pereira\"\n", "__email__ = \"weslley.dasilvapereira@nrel.gov\"\n", "__credits__ = [\"Weslley S. Pereira\"]\n", - "__version__ = \"0.4.0\"\n", + "__version__ = \"0.4.1\"\n", "__deprecated__ = False" ] }, diff --git a/examples/multiobj/socemo.ipynb b/examples/multiobj/socemo.ipynb index f474c403..46ebd721 100644 --- a/examples/multiobj/socemo.ipynb +++ b/examples/multiobj/socemo.ipynb @@ -28,7 +28,7 @@ "__maintainer__ = \"Weslley S. Pereira\"\n", "__email__ = \"weslley.dasilvapereira@nrel.gov\"\n", "__credits__ = [\"Weslley S. Pereira\"]\n", - "__version__ = \"0.4.0\"\n", + "__version__ = \"0.4.1\"\n", "__deprecated__ = False" ] }, diff --git a/examples/opt_with_constr/example_gosac_1.py b/examples/opt_with_constr/example_gosac_1.py index 6b4d9fcb..557f3875 100644 --- a/examples/opt_with_constr/example_gosac_1.py +++ b/examples/opt_with_constr/example_gosac_1.py @@ -20,7 +20,7 @@ __maintainer__ = "Weslley S. Pereira" __email__ = "weslley.dasilvapereira@nrel.gov" __credits__ = ["Juliane Mueller", "Weslley S. Pereira"] -__version__ = "0.4.0" +__version__ = "0.4.1" __deprecated__ = False from blackboxopt.optimize import gosac diff --git a/examples/opt_with_constr/example_gosac_2.py b/examples/opt_with_constr/example_gosac_2.py index 22ae1f6a..34f32e8f 100644 --- a/examples/opt_with_constr/example_gosac_2.py +++ b/examples/opt_with_constr/example_gosac_2.py @@ -20,7 +20,7 @@ __maintainer__ = "Weslley S. Pereira" __email__ = "weslley.dasilvapereira@nrel.gov" __credits__ = ["Juliane Mueller", "Weslley S. Pereira"] -__version__ = "0.4.0" +__version__ = "0.4.1" __deprecated__ = False from blackboxopt.optimize import gosac diff --git a/examples/sampling.ipynb b/examples/sampling.ipynb index f954138c..413766af 100644 --- a/examples/sampling.ipynb +++ b/examples/sampling.ipynb @@ -28,7 +28,7 @@ "__maintainer__ = \"Weslley S. Pereira\"\n", "__email__ = \"weslley.dasilvapereira@nrel.gov\"\n", "__credits__ = [\"Weslley S. Pereira\"]\n", - "__version__ = \"0.4.0\"\n", + "__version__ = \"0.4.1\"\n", "__deprecated__ = False" ] }, diff --git a/examples/single_obj_rbf/LocalStochRBFstop.py b/examples/single_obj_rbf/LocalStochRBFstop.py index d6d3fde0..aa8edfaf 100644 --- a/examples/single_obj_rbf/LocalStochRBFstop.py +++ b/examples/single_obj_rbf/LocalStochRBFstop.py @@ -26,7 +26,7 @@ "Haoyu Jia", "Weslley S. Pereira", ] -__version__ = "0.4.0" +__version__ = "0.4.1" __deprecated__ = False from optprogram1 import read_check_data_file diff --git a/examples/single_obj_rbf/compareLearningStrategies.py b/examples/single_obj_rbf/compareLearningStrategies.py index 7177b694..161e1f62 100644 --- a/examples/single_obj_rbf/compareLearningStrategies.py +++ b/examples/single_obj_rbf/compareLearningStrategies.py @@ -20,7 +20,7 @@ __maintainer__ = "Weslley S. Pereira" __email__ = "weslley.dasilvapereira@nrel.gov" __credits__ = ["Weslley S. Pereira"] -__version__ = "0.4.0" +__version__ = "0.4.1" __deprecated__ = False diff --git a/examples/single_obj_rbf/data.py b/examples/single_obj_rbf/data.py index 6da3f00b..5183a485 100644 --- a/examples/single_obj_rbf/data.py +++ b/examples/single_obj_rbf/data.py @@ -26,7 +26,7 @@ "Haoyu Jia", "Weslley S. Pereira", ] -__version__ = "0.4.0" +__version__ = "0.4.1" __deprecated__ = False from dataclasses import dataclass diff --git a/examples/single_obj_rbf/datainput_Branin.py b/examples/single_obj_rbf/datainput_Branin.py index 5ad5bf4b..56f46ba9 100644 --- a/examples/single_obj_rbf/datainput_Branin.py +++ b/examples/single_obj_rbf/datainput_Branin.py @@ -26,7 +26,7 @@ "Haoyu Jia", "Weslley S. Pereira", ] -__version__ = "0.4.0" +__version__ = "0.4.1" __deprecated__ = False import numpy as np diff --git a/examples/single_obj_rbf/datainput_BraninWithInteger.py b/examples/single_obj_rbf/datainput_BraninWithInteger.py index 0eec7319..056f2cf1 100644 --- a/examples/single_obj_rbf/datainput_BraninWithInteger.py +++ b/examples/single_obj_rbf/datainput_BraninWithInteger.py @@ -26,7 +26,7 @@ "Haoyu Jia", "Weslley S. Pereira", ] -__version__ = "0.4.0" +__version__ = "0.4.1" __deprecated__ = False import numpy as np diff --git a/examples/single_obj_rbf/datainput_hartman3.py b/examples/single_obj_rbf/datainput_hartman3.py index d2c810c0..da39411a 100644 --- a/examples/single_obj_rbf/datainput_hartman3.py +++ b/examples/single_obj_rbf/datainput_hartman3.py @@ -26,7 +26,7 @@ "Haoyu Jia", "Weslley S. Pereira", ] -__version__ = "0.4.0" +__version__ = "0.4.1" __deprecated__ = False import numpy as np diff --git a/examples/single_obj_rbf/datainput_rastrigin.py b/examples/single_obj_rbf/datainput_rastrigin.py index 2757e68c..36ceeae7 100644 --- a/examples/single_obj_rbf/datainput_rastrigin.py +++ b/examples/single_obj_rbf/datainput_rastrigin.py @@ -26,7 +26,7 @@ "Haoyu Jia", "Weslley S. Pereira", ] -__version__ = "0.4.0" +__version__ = "0.4.1" __deprecated__ = False import numpy as np diff --git a/examples/single_obj_rbf/optprogram1.py b/examples/single_obj_rbf/optprogram1.py index 3bfa7a94..a12c351d 100644 --- a/examples/single_obj_rbf/optprogram1.py +++ b/examples/single_obj_rbf/optprogram1.py @@ -31,7 +31,7 @@ "Haoyu Jia", "Weslley S. Pereira", ] -__version__ = "0.4.0" +__version__ = "0.4.1" __deprecated__ = False diff --git a/examples/vlse_benchmark/vlse_bench.ipynb b/examples/vlse_benchmark/vlse_bench.ipynb index 56918339..d4e57b75 100644 --- a/examples/vlse_benchmark/vlse_bench.ipynb +++ b/examples/vlse_benchmark/vlse_bench.ipynb @@ -28,7 +28,7 @@ "__maintainer__ = \"Weslley S. Pereira\"\n", "__email__ = \"weslley.dasilvapereira@nrel.gov\"\n", "__credits__ = [\"Weslley S. Pereira\"]\n", - "__version__ = \"0.4.0\"\n", + "__version__ = \"0.4.1\"\n", "__deprecated__ = False" ] }, diff --git a/examples/vlse_benchmark/vlse_bench.py b/examples/vlse_benchmark/vlse_bench.py index ed5393b2..d9c28816 100644 --- a/examples/vlse_benchmark/vlse_bench.py +++ b/examples/vlse_benchmark/vlse_bench.py @@ -20,7 +20,7 @@ __maintainer__ = "Weslley S. Pereira" __email__ = "weslley.dasilvapereira@nrel.gov" __credits__ = ["Weslley S. Pereira"] -__version__ = "0.4.0" +__version__ = "0.4.1" __deprecated__ = False import os diff --git a/pyproject.toml b/pyproject.toml index a23b1f50..ff407e5b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "blackboxopt" -version = "0.4.0" +version = "0.4.1" description = "Surrogate models and active learning for scientific applications" authors = [ {name = "Weslley da Silva Pereira", email = "weslley.dasilvapereira@nrel.gov"}, diff --git a/tests/test_optimize.py b/tests/test_optimize.py index 1e44cae7..8be4242d 100644 --- a/tests/test_optimize.py +++ b/tests/test_optimize.py @@ -20,7 +20,7 @@ __maintainer__ = "Weslley S. Pereira" __email__ = "weslley.dasilvapereira@nrel.gov" __credits__ = ["Weslley S. Pereira"] -__version__ = "0.4.0" +__version__ = "0.4.1" __deprecated__ = False import numpy as np diff --git a/tests/test_rbf.py b/tests/test_rbf.py index 1598080b..389b328a 100644 --- a/tests/test_rbf.py +++ b/tests/test_rbf.py @@ -20,7 +20,7 @@ __maintainer__ = "Weslley S. Pereira" __email__ = "weslley.dasilvapereira@nrel.gov" __credits__ = ["Weslley S. Pereira"] -__version__ = "0.4.0" +__version__ = "0.4.1" __deprecated__ = False import numpy as np diff --git a/tests/test_sampling.py b/tests/test_sampling.py index dc84d258..221ae184 100644 --- a/tests/test_sampling.py +++ b/tests/test_sampling.py @@ -20,7 +20,7 @@ __maintainer__ = "Weslley S. Pereira" __email__ = "weslley.dasilvapereira@nrel.gov" __credits__ = ["Weslley S. Pereira"] -__version__ = "0.4.0" +__version__ = "0.4.1" __deprecated__ = False import numpy as np diff --git a/tests/test_vlse_bench.py b/tests/test_vlse_bench.py index 0ea36933..747d1b0c 100644 --- a/tests/test_vlse_bench.py +++ b/tests/test_vlse_bench.py @@ -20,7 +20,7 @@ __maintainer__ = "Weslley S. Pereira" __email__ = "weslley.dasilvapereira@nrel.gov" __credits__ = ["Weslley S. Pereira"] -__version__ = "0.4.0" +__version__ = "0.4.1" __deprecated__ = False from copy import deepcopy diff --git a/tests/vlse_benchmark/__init__.py b/tests/vlse_benchmark/__init__.py index e7910b12..13ad92f2 100644 --- a/tests/vlse_benchmark/__init__.py +++ b/tests/vlse_benchmark/__init__.py @@ -27,7 +27,7 @@ __maintainer__ = "Weslley S. Pereira" __email__ = "weslley.dasilvapereira@nrel.gov" __credits__ = ["Sonja Surjanovic", "Derek Bingham", "Weslley S. Pereira"] -__version__ = "0.4.0" +__version__ = "0.4.1" __deprecated__ = False from rpy2.robjects import r From 61f5677362173e4246c4a4c8ce89a762c94fbb48 Mon Sep 17 00:00:00 2001 From: Weslley da Silva Pereira Date: Fri, 28 Jun 2024 14:42:47 -0600 Subject: [PATCH 13/24] Add more kernel functions to the RBF model --- blackboxopt/acquisition.py | 42 +-- blackboxopt/optimize.py | 2 +- blackboxopt/problem.py | 4 +- blackboxopt/rbf.py | 334 +++++------------- blackboxopt/rbf_kernel.py | 211 +++++++++++ examples/multiobj/socemo.ipynb | 4 +- examples/single_obj_rbf/LocalStochRBFstop.py | 4 +- .../compareLearningStrategies.py | 16 +- examples/single_obj_rbf/optprogram1.py | 16 +- tests/test_rbf.py | 20 +- tests/test_vlse_bench.py | 2 +- 11 files changed, 344 insertions(+), 311 deletions(-) create mode 100644 blackboxopt/rbf_kernel.py diff --git a/blackboxopt/acquisition.py b/blackboxopt/acquisition.py index 1c67100e..247504e8 100644 --- a/blackboxopt/acquisition.py +++ b/blackboxopt/acquisition.py @@ -53,7 +53,7 @@ # Local imports from .sampling import NormalSampler, Sampler -from .rbf import RbfModel, RbfType +from .rbf import RbfModel, RbfKernel from .problem import ( ProblemWithConstraint, ProblemNoConstraint, @@ -376,13 +376,13 @@ def acquire( # Evaluate candidates if not listOfSurrogates: samples = surrogateModel.samples() - fx, _ = surrogateModel.eval(x) + fx, _ = surrogateModel(x) else: samples = surrogateModel[0].samples() objdim = len(surrogateModel) fx = np.empty((nCand, objdim)) for i in range(objdim): - fx[:, i], _ = surrogateModel[i].eval(x) + fx[:, i], _ = surrogateModel[i](x) # Create scaled x and scaled distx xlow = np.array([bounds[i][0] for i in range(dim)]) @@ -494,13 +494,13 @@ def acquire( # Evaluate candidates if not listOfSurrogates: samples = surrogateModel.samples() - fx, _ = surrogateModel.eval(x) + fx, _ = surrogateModel(x) else: samples = surrogateModel[0].samples() objdim = len(surrogateModel) fx = np.empty((nCand, objdim)) for i in range(objdim): - fx[:, i], _ = surrogateModel[i].eval(x) + fx[:, i], _ = surrogateModel[i](x) # Create scaled x and scaled distx xlow = np.array([bounds[i][0] for i in range(dim)]) @@ -636,7 +636,7 @@ def acquire( assert len(fbounds) == 2 # find min of surrogate model problem = ProblemNoConstraint( - lambda x: surrogateModel.eval(x)[0], + lambda x: surrogateModel(x)[0], bounds, surrogateModel.iindex, ) @@ -691,7 +691,7 @@ def acquire( assert len(fbounds) == 2 # find the minimum of RBF surface problem = ProblemNoConstraint( - lambda x: surrogateModel.eval(x)[0], + lambda x: surrogateModel(x)[0], bounds, surrogateModel.iindex, ) @@ -871,9 +871,7 @@ def acquire( ].T # Evaluate the surrogate model on the candidate points and sort them - fcand[iStart:iEnd], _ = surrogateModel.eval( - candidates[iStart:iEnd, :] - ) + fcand[iStart:iEnd], _ = surrogateModel(candidates[iStart:iEnd, :]) ids = np.argsort(fcand[0:iEnd]) remevals -= iEnd - iStart @@ -899,26 +897,18 @@ def acquire( def func_continuous_search(x): x_ = xi.copy() x_[cindex] = x - return surrogateModel.eval(x_)[0] + return surrogateModel(x_)[0] def dfunc_continuous_search(x): x_ = xi.copy() x_[cindex] = x return surrogateModel.jac(x_)[cindex] - # def hessp_continuous_search(x, p): - # x_ = xi.copy() - # x_[cindex] = x - # p_ = np.zeros(dim) - # p_[cindex] = p - # return surrogateModel.hessp(x_, p_)[cindex] - res = minimize( func_continuous_search, xi[cindex], method="L-BFGS-B", jac=dfunc_continuous_search, - # hessp=hessp_continuous_search, bounds=cbounds, options={ "maxfun": remevals, @@ -1025,7 +1015,7 @@ def pareto_front_target(self, paretoFront: np.ndarray) -> np.ndarray: assert objdim > 1 # Create a surrogate model for the Pareto front in the objective space - paretoModel = RbfModel(RbfType.LINEAR) + paretoModel = RbfModel(RbfKernel.LINEAR) k = np.random.choice(objdim) paretoModel.update_samples( np.array([paretoFront[:, i] for i in range(objdim) if i != k]).T @@ -1046,13 +1036,13 @@ def pareto_front_target(self, paretoFront: np.ndarray) -> np.ndarray: ) def delta_f(tau): - tauk, _ = paretoModel.eval(tau) + tauk, _ = paretoModel(tau) _tau = np.concatenate((tau[0:k], tauk, tau[k:])) return -tree.query(_tau)[0] # Minimize delta_f res = differential_evolution(delta_f, boundsPareto) - tauk, _ = paretoModel.eval(res.x) + tauk, _ = paretoModel(res.x) tau = np.concatenate((res.x[0:k], tauk, res.x[k:])) return tau @@ -1175,7 +1165,7 @@ def acquire( endpoints = np.empty((objdim, dim)) for i in range(objdim): minimumPointProblem = ProblemNoConstraint( - lambda x: surrogateModels[i].eval(x)[0], bounds, iindex + lambda x: surrogateModels[i](x)[0], bounds, iindex ) res = pymoo_minimize( minimumPointProblem, @@ -1421,9 +1411,7 @@ def acquire( fnondominatedAndBestCandidates = np.concatenate( ( paretoFront, - np.array( - [s.eval(bestCandidates)[0] for s in surrogateModels] - ).T, + np.array([s(bestCandidates)[0] for s in surrogateModels]).T, ), axis=0, ) @@ -1508,7 +1496,7 @@ def acquire( cheapProblem = ProblemWithConstraint( self.fun, lambda x: np.transpose( - [surrogateModels[i].eval(x)[0] for i in range(gdim)] + [surrogateModels[i](x)[0] for i in range(gdim)] ), bounds, iindex, diff --git a/blackboxopt/optimize.py b/blackboxopt/optimize.py index 74dadd63..c6bc4416 100644 --- a/blackboxopt/optimize.py +++ b/blackboxopt/optimize.py @@ -1681,7 +1681,7 @@ def gosac( # Evaluate the surrogate at the best candidates sCandidates = np.empty((len(bestCandidates), gdim)) for i in range(gdim): - sCandidates[:, i], _ = surrogateModels[i].eval(bestCandidates) + sCandidates[:, i], _ = surrogateModels[i](bestCandidates) # Find the minimum number of constraint violations constraintViolation = [ diff --git a/blackboxopt/problem.py b/blackboxopt/problem.py index 1568073a..a8d51dcf 100644 --- a/blackboxopt/problem.py +++ b/blackboxopt/problem.py @@ -161,7 +161,7 @@ def _evaluate(self, X, out): out["F"] = np.empty((x.shape[0], self.n_obj)) for i in range(self.n_obj): out["F"][:, i] = np.absolute( - self.surrogateModels[i].eval(x)[0] - self.tau[i] + self.surrogateModels[i](x)[0] - self.tau[i] ) @@ -185,4 +185,4 @@ def _evaluate(self, X, out): x = _dict_to_array(X) out["F"] = np.empty((x.shape[0], self.n_obj)) for i in range(self.n_obj): - out["F"][:, i] = self.surrogateModels[i].eval(x)[0] + out["F"][:, i] = self.surrogateModels[i](x)[0] diff --git a/blackboxopt/rbf.py b/blackboxopt/rbf.py index c9d2f504..85433c2c 100644 --- a/blackboxopt/rbf.py +++ b/blackboxopt/rbf.py @@ -26,16 +26,40 @@ from typing import Optional import warnings import numpy as np -from enum import Enum # Scipy imports from scipy.spatial.distance import cdist from scipy.linalg import solve, solve_triangular +from scipy.special import comb # Local imports from .sampling import Sampler +from .rbf_kernel import RbfKernel, KERNEL_DERIVATIVE_OVER_R_FUNC, KERNEL_FUNC -RbfType = Enum("RbfType", ["LINEAR", "CUBIC", "THINPLATE"]) + +def _order2_monomials(x: np.ndarray) -> np.ndarray: + m = x.shape[0] + dim = x.shape[1] + out = np.zeros((m, (dim * (dim + 1)) // 2)) + count = 0 + for i in range(dim): + for j in range(i, dim): + out[:, count] = x[:, i] * x[:, j] + count += 1 + return out + + +def _d_order2_monomials(x: np.ndarray) -> np.ndarray: + dim = len(x) + assert x.ndim == 1 + out = np.zeros((dim, (dim * (dim + 1)) // 2)) + count = 0 + for i in range(dim): + for j in range(i, dim): + out[i, count] += x[j] + out[j, count] += x[i] + count += 1 + return out class RbfFilter: @@ -95,12 +119,8 @@ class RbfModel: Attributes ---------- - type : RbfType, optional - Defines the function phi used in the RBF model. The options are: - - - RbfType.LINEAR: phi(r) = r. - - RbfType.CUBIC: phi(r) = r^3. - - RbfType.THINPLATE: phi(r) = r^2 * log(r). + type : RbfKernel, optional + Defines the function phi used in the RBF model. The options are listed in the RbfKernel enum. iindex : tuple, optional Indices of the input space that are integer. The default is (). filter : RbfFilter, optional @@ -110,14 +130,24 @@ class RbfModel: def __init__( self, - rbf_type: RbfType = RbfType.CUBIC, + kernel: RbfKernel = RbfKernel.CUBIC, iindex: tuple[int, ...] = (), filter: Optional[RbfFilter] = None, ): - self.type = rbf_type self.iindex = iindex self.filter = RbfFilter() if filter is None else filter + # Set kernel and the degree of the polynomial tail + self._kernel = kernel + if kernel in (RbfKernel.LINEAR, RbfKernel.MULTIQUADRIC): + self._degree = 0 + elif kernel in (RbfKernel.CUBIC, RbfKernel.THINPLATE): + self._degree = 1 + elif kernel == RbfKernel.QUINTIC: + self._degree = 2 + else: + self._degree = None + self._valid_coefficients = True self._m = 0 self._x = np.array([]) @@ -125,6 +155,7 @@ def __init__( self._coef = np.array([]) self._PHI = np.array([]) self._P = np.array([]) + self._POWERS = np.array([], dtype=np.dtype("long")) def reserve(self, maxeval: int, dim: int) -> None: """Reserve space for the RBF model. @@ -221,137 +252,11 @@ def pdim(self) -> int: Dimension of the polynomial tail. """ dim = self.dim() - if self.type == RbfType.LINEAR: - return 1 - elif self.type in (RbfType.CUBIC, RbfType.THINPLATE): - return 1 + dim - else: - raise ValueError("Unknown RBF type") - - def phi(self, r): - """Applies the function phi to the distance(s) r. - - Parameters - ---------- - r : array_like - Distance(s) between points. - - Returns - ------- - out: array_like - Phi-value of the distances provided on input. - """ - if self.type == RbfType.LINEAR: - return r - elif self.type == RbfType.CUBIC: - return np.power(r, 3) - elif self.type == RbfType.THINPLATE: - if not hasattr(r, "__len__"): - if r > 0: - return r**2 * np.log(r) - else: - return 0 - else: - ret = np.zeros_like(r) - ret[r > 0] = np.multiply( - np.power(r[r > 0], 2), np.log(r[r > 0]) - ) - return ret - else: - raise ValueError("Unknown RBF type") - - def dphi(self, r): - """Derivative of the function phi at the distance(s) r. - - Parameters - ---------- - r : array_like - Distance(s) between points. - - Returns - ------- - out: array_like - Derivative of the phi-value of the distances provided on input. - """ - if self.type == RbfType.LINEAR: - return np.ones(r.shape) - elif self.type == RbfType.CUBIC: - return 3 * np.power(r, 2) - elif self.type == RbfType.THINPLATE: - if not hasattr(r, "__len__"): - if r > 0: - return 2 * r * np.log(r) + r - else: - return 0 - else: - ret = np.zeros_like(r) - ret[r > 0] = ( - 2 * np.multiply(r[r > 0], np.log(r[r > 0])) + r[r > 0] - ) - return ret - else: - raise ValueError("Unknown RBF type") - - def dphiOverR(self, r): - """Derivative of the function phi divided by r at the distance(s) r. - - Parameters - ---------- - r : array_like - Distance(s) between points. - - Returns - ------- - out: array_like - Derivative of the phi-value of the distances provided on input - divided by the distance. - """ - if self.type == RbfType.LINEAR: - return np.ones(r.shape) / r - elif self.type == RbfType.CUBIC: - return 3 * r - elif self.type == RbfType.THINPLATE: - if not hasattr(r, "__len__"): - if r > 0: - return 2 * np.log(r) + 1 - else: - return 0 - else: - ret = np.zeros_like(r) - ret[r > 0] = 2 * np.log(r[r > 0]) + 1 - return ret - else: - raise ValueError("Unknown RBF type") - - def ddphi(self, r): - """Second derivative of the function phi at the distance(s) r. - - Parameters - ---------- - r : array_like - Distance(s) between points. - Returns - ------- - out: array_like - Second derivative of the phi-value of the distances provided on input. - """ - if self.type == RbfType.LINEAR: - return np.zeros(r.shape) - elif self.type == RbfType.CUBIC: - return 6 * r - elif self.type == RbfType.THINPLATE: - if not hasattr(r, "__len__"): - if r > 0: - return 2 * np.log(r) + 3 - else: - return 0 - else: - ret = np.zeros_like(r) - ret[r > 0] = 2 * np.log(r[r > 0]) + 3 - return ret + if self._degree is not None: + return int(comb(dim + self._degree, dim, exact=True)) else: - raise ValueError("Unknown RBF type") + return 0 def pbasis(self, x: np.ndarray) -> np.ndarray: """Computes the polynomial tail matrix for a given set of points. @@ -368,14 +273,20 @@ def pbasis(self, x: np.ndarray) -> np.ndarray: """ dim = self.dim() m = x.size // dim + assert self._degree is not None # Set up the polynomial tail matrix P - if self.type == RbfType.LINEAR: - return np.ones((m, 1)) - elif self.type in (RbfType.CUBIC, RbfType.THINPLATE): - return np.concatenate((np.ones((m, 1)), x.reshape(m, -1)), axis=1) - else: - raise ValueError("Invalid polynomial tail") + out = np.ones((m, 1)) + if self._degree >= 1: + out = np.concatenate((out, x.reshape(m, -1)), axis=1) + if self._degree >= 2: + out = np.concatenate( + (out, _order2_monomials(x.reshape(m, -1))), axis=1 + ) + if self._degree >= 3: + raise ValueError("Higher order polynomials are not supported") + + return out def dpbasis(self, x: np.ndarray) -> np.ndarray: """Computes the derivative of the polynomial tail matrix for a given x. @@ -391,41 +302,19 @@ def dpbasis(self, x: np.ndarray) -> np.ndarray: Derivative of the polynomial tail matrix for the input point. """ dim = self.dim() + assert self._degree is not None - if self.type == RbfType.LINEAR: - return np.zeros((1, 1)) - elif self.type in (RbfType.CUBIC, RbfType.THINPLATE): - return np.concatenate((np.zeros((1, dim)), np.eye(dim)), axis=0) - else: - raise ValueError("Invalid polynomial tail") - - def ddpbasis(self, x: np.ndarray, p: np.ndarray) -> np.ndarray: - """Computes the second derivative of the polynomial tail matrix for a - given x and direction p. - - Parameters - ---------- - x : numpy.ndarray - Point in a d-dimensional space. - p : numpy.ndarray - Direction in which the second derivative is evaluated. - - Returns - ------- - out: numpy.ndarray - Second derivative of the polynomial tail matrix for the input point - and direction. - """ - dim = self.dim() + out = np.zeros((dim, 1)) + if self._degree >= 1: + out = np.concatenate((out, np.eye(dim)), axis=1) + if self._degree >= 2: + out = np.concatenate((out, _d_order2_monomials(x).T), axis=1) + if self._degree >= 3: + raise ValueError("Higher order polynomials are not supported") - if self.type == RbfType.LINEAR: - return np.zeros((1, 1)) - elif self.type in (RbfType.CUBIC, RbfType.THINPLATE): - return np.zeros((dim + 1, dim)) - else: - raise ValueError("Invalid polynomial tail") + return out - def eval(self, x: np.ndarray) -> tuple[np.ndarray, np.ndarray]: + def __call__(self, x: np.ndarray) -> tuple[np.ndarray, np.ndarray]: """Evaluates the model at one or multiple points. Parameters @@ -447,12 +336,13 @@ def eval(self, x: np.ndarray) -> tuple[np.ndarray, np.ndarray]: ) dim = self.dim() + phi = KERNEL_FUNC[self._kernel] # compute pairwise distances between candidates and sampled points D = cdist(x.reshape(-1, dim), self.samples()) Px = self.pbasis(x) - y = np.matmul(self.phi(D), self._coef[0 : self._m]) + np.dot( + y = np.matmul(phi(D), self._coef[0 : self._m]) + np.dot( Px, self._coef[self._m : self._m + Px.shape[1]] ) @@ -482,65 +372,16 @@ def jac(self, x: np.ndarray) -> np.ndarray: ) dim = self.dim() + dphiOverR = KERNEL_DERIVATIVE_OVER_R_FUNC[self._kernel] # compute pairwise distances between candidates and sampled points d = cdist(x.reshape(-1, dim), self.samples()).flatten() - A = np.array([self.dphiOverR(d[i]) * x for i in range(d.size)]) + A = np.array([dphiOverR(d[i]) * x for i in range(d.size)]) B = self.dpbasis(x) y = np.matmul(A.T, self._coef[0 : self._m]) + np.matmul( - B.T, self._coef[self._m : self._m + B.shape[0]] - ) - - return y.flatten() - - def hessp(self, x: np.ndarray, p: np.ndarray) -> np.ndarray: - r"""Evaluates the Hessian of the model at x in the direction of p. - - .. math:: - - H(f)(x) v = \sum_{i=1}^{m} \beta_i \left( - \phi''(\|x - x_i\|)\frac{(x^Tv)x}{\|x - x_i\|^2} + - \frac{\phi'(\|x - x_i\|)}{\|x - x_i\|} - \left(v - \frac{(x^Tv)x}{\|x - x_i\|^2}\right) - \right) - + \sum_{i=1}^{n} \beta_{m+i} H(p_i)(x) v. - - Parameters - ---------- - x : np.ndarray - Point in a d-dimensional space. - p : np.ndarray - Direction in which the Hessian is evaluated. - - Returns - ------- - numpy.ndarray - Value for the Hessian of the RBF model at x in the direction of p. - """ - if self._valid_coefficients is False: - raise RuntimeError( - "Invalid coefficients. Run update_coefficients() before evaluating the model." - ) - - dim = self.dim() - - # compute pairwise distances between candidates and sampled points - d = cdist(x.reshape(-1, dim), self.samples()).flatten() - - xxTp = np.dot(p, x) * x - A = np.array( - [ - self.ddphi(d[i]) * (xxTp / (d[i] * d[i])) - + self.dphiOverR(d[i]) * (p - (xxTp / (d[i] * d[i]))) - for i in range(d.size) - ] - ) - B = self.ddpbasis(x, p) - - y = np.matmul(A.T, self._coef[0 : self._m]) + np.matmul( - B.T, self._coef[self._m : self._m + B.shape[0]] + B, self._coef[self._m : self._m + B.shape[1]] ) return y.flatten() @@ -624,7 +465,8 @@ def update_samples(self, xNew: np.ndarray, distNew=None) -> None: self.reserve(m, dim) # Update matrices _PHI and _P - self._PHI[oldm:m, 0:m] = self.phi(distNew) + phi = KERNEL_FUNC[self._kernel] + self._PHI[oldm:m, 0:m] = phi(distNew) self._PHI[0:oldm, oldm:m] = self._PHI[oldm:m, 0:oldm].T self._P[oldm:m, :] = self.pbasis(xNew) @@ -684,7 +526,8 @@ def create_initial_design( distNew = cdist(self.samples(), self.samples()) # Set matrix _PHI - self._PHI[0:m, 0:m] = self.phi(distNew) + phi = KERNEL_FUNC[self._kernel] + self._PHI[0:m, 0:m] = phi(distNew) self._PHI[0:0, 0:m] = self._PHI[0:m, 0:0].T # Coefficients are not valid @@ -791,11 +634,13 @@ def mu_measure(self, x: np.ndarray, xdist=None, LDLt=()) -> float: Optimization. Journal of Global Optimization 19, 201–227 (2001). https://doi.org/10.1023/A:1011255519438 """ + phi = KERNEL_FUNC[self._kernel] + # compute rbf value of the new point x if xdist is None: xdist = cdist(x.reshape(1, -1), self.samples()) newRow = np.concatenate( - (np.asarray(self.phi(xdist)).flatten(), self.pbasis(x).flatten()) + (np.asarray(phi(xdist)).flatten(), self.pbasis(x).flatten()) ) if LDLt: @@ -833,7 +678,7 @@ def mu_measure(self, x: np.ndarray, xdist=None, LDLt=()) -> float: l01[i] /= d0[i, i] # 3. d = \phi(0) - l_{01}^T D_0 l_{01} and \mu = 1/d - d = self.phi(0) - np.dot(l01, D0l01) + d = phi(0) - np.dot(l01, D0l01) mu = 1 / d if d != 0 else np.inf if not LDLt or mu == np.inf: @@ -841,7 +686,7 @@ def mu_measure(self, x: np.ndarray, xdist=None, LDLt=()) -> float: A_aug = np.block( [ [self.get_RBFmatrix(), newRow.reshape(-1, 1)], - [newRow, self.phi(0)], + [newRow, phi(0)], ] ) @@ -857,16 +702,7 @@ def mu_measure(self, x: np.ndarray, xdist=None, LDLt=()) -> float: # Return huge value, only occurs if the matrix is ill-conditioned mu = np.inf - # Order of the polynomial tail - if self.type == RbfType.LINEAR: - m0 = 0 - elif self.type in (RbfType.CUBIC, RbfType.THINPLATE): - m0 = 1 - else: - raise ValueError("Unknown RBF type") - # Get the absolute value of mu - mu *= (-1) ** (m0 + 1) if mu < 0: # Return huge value, only occurs if the matrix is ill-conditioned return np.inf @@ -898,16 +734,16 @@ def bumpiness_measure(self, x: np.ndarray, target, LDLt=()) -> float: Optimization. Journal of Global Optimization 19, 201–227 (2001). https://doi.org/10.1023/A:1011255519438 """ - absmu = self.mu_measure(x, LDLt=LDLt) + mu = self.mu_measure(x, LDLt=LDLt) assert ( - absmu > 0 + mu > 0 ) # if absmu == 0, the linear system in the surrogate model singular - if absmu == np.inf: + if mu == np.inf: # Return huge value, only occurs if the matrix is ill-conditioned return np.inf # predict RBF value of x - yhat, _ = self.eval(x) + yhat, _ = self(x) assert yhat.size == 1 # sanity check # Compute the distance between the predicted value and the target @@ -916,5 +752,5 @@ def bumpiness_measure(self, x: np.ndarray, target, LDLt=()) -> float: # dist = tol # use sqrt(gn) as the bumpiness measure to avoid underflow - sqrtgn = np.sqrt(absmu) * dist + sqrtgn = np.sqrt(mu) * dist return sqrtgn diff --git a/blackboxopt/rbf_kernel.py b/blackboxopt/rbf_kernel.py new file mode 100644 index 00000000..b0ac5bab --- /dev/null +++ b/blackboxopt/rbf_kernel.py @@ -0,0 +1,211 @@ +from enum import Enum +from types import MappingProxyType +import numpy as np + +RbfKernel = Enum( + "RbfKernel", + [ + "LINEAR", + "CUBIC", + "THINPLATE", + "QUINTIC", + "MULTIQUADRIC", + "INVERSE_MULTIQUADRIC", + "INVERSE_QUADRATIC", + "GAUSSIAN", + ], +) + +# Kernel functions + + +def linear(r): + return np.negative(r) + + +def thin_plate_spline(r): + if not hasattr(r, "__len__"): + ret = 1 if r == 0 else r + else: + ret = np.where(np.asarray(r) == 0, 1, r) + return ret**2 * np.log(ret) + + +def cubic(r): + return np.power(r, 3) + + +def quintic(r): + return -np.power(r, 5) + + +def multiquadric(r): + return -np.sqrt(np.power(r, 2) + 1) + + +def inverse_multiquadric(r): + return 1 / np.sqrt(np.power(r, 2) + 1) + + +def inverse_quadratic(r): + return 1 / (np.power(r, 2) + 1) + + +def gaussian(r): + return np.exp(-np.power(r, 2)) + + +# Kernel derivatives + + +def d_linear(r: np.ndarray): + return -np.ones(r.shape) + + +def d_thin_plate_spline(r: np.ndarray): + ret = np.where(r == 0, 1, r) + return 2 * ret * np.log(ret) + ret + + +def d_cubic(r: np.ndarray): + return 3 * r**2 + + +def d_quintic(r: np.ndarray): + return -5 * r**4 + + +def d_multiquadric(r: np.ndarray): + return -r / np.sqrt(r**2 + 1) + + +def d_inverse_multiquadric(r: np.ndarray): + return -r / np.sqrt(r**2 + 1) ** 3 + + +def d_inverse_quadratic(r: np.ndarray): + return -2 * r / (r**2 + 1) ** 2 + + +def d_gaussian(r: np.ndarray): + return -2 * r * np.exp(-(r**2)) + + +# Kernel derivatives over r + + +def d_linear_over_r(r: np.ndarray): + return -1 / r + + +def d_thin_plate_spline_over_r(r: np.ndarray): + return 2 * np.log(r) + 1 + + +def d_cubic_over_r(r: np.ndarray): + return 3 * r + + +def d_quintic_over_r(r: np.ndarray): + return -5 * r**3 + + +def d_multiquadric_over_r(r: np.ndarray): + return -1 / np.sqrt(r**2 + 1) + + +def d_inverse_multiquadric_over_r(r: np.ndarray): + return -1 / np.sqrt(r**2 + 1) ** 3 + + +def d_inverse_quadratic_over_r(r: np.ndarray): + return -2 / (r**2 + 1) ** 2 + + +# Kernel second derivatives + + +def d2_linear(r: np.ndarray): + return np.zeros(r.shape) + + +def d2_thin_plate_spline(r: np.ndarray): + ret = np.where(r == 0, 1, r) + return 2 * np.log(ret) + 3 + + +def d2_cubic(r: np.ndarray): + return 6 * r + + +def d2_quintic(r: np.ndarray): + return -20 * r**3 + + +def d2_multiquadric(r: np.ndarray): + return -1 / np.sqrt(r**2 + 1) ** 3 + + +def d2_inverse_multiquadric(r: np.ndarray): + return (2 * r**2 - 1) / np.sqrt(r**2 + 1) ** 5 + + +def d2_inverse_quadratic(r: np.ndarray): + return (6 * r**2 - 2) / (r**2 + 1) ** 3 + + +def d2_gaussian(r: np.ndarray): + return (4 * r**2 - 2) * np.exp(-(r**2)) + + +KERNEL_FUNC = MappingProxyType( + { + RbfKernel.LINEAR: linear, + RbfKernel.CUBIC: cubic, + RbfKernel.THINPLATE: thin_plate_spline, + RbfKernel.QUINTIC: quintic, + RbfKernel.MULTIQUADRIC: multiquadric, + RbfKernel.INVERSE_MULTIQUADRIC: inverse_multiquadric, + RbfKernel.INVERSE_QUADRATIC: inverse_quadratic, + RbfKernel.GAUSSIAN: gaussian, + } +) + +KERNEL_DERIVATIVE_FUNC = MappingProxyType( + { + RbfKernel.LINEAR: d_linear, + RbfKernel.CUBIC: d_cubic, + RbfKernel.THINPLATE: d_thin_plate_spline, + RbfKernel.QUINTIC: d_quintic, + RbfKernel.MULTIQUADRIC: d_multiquadric, + RbfKernel.INVERSE_MULTIQUADRIC: d_inverse_multiquadric, + RbfKernel.INVERSE_QUADRATIC: d_inverse_quadratic, + RbfKernel.GAUSSIAN: d_gaussian, + } +) + +KERNEL_DERIVATIVE_OVER_R_FUNC = MappingProxyType( + { + RbfKernel.LINEAR: d_linear_over_r, + RbfKernel.CUBIC: d_cubic_over_r, + RbfKernel.THINPLATE: d_thin_plate_spline_over_r, + RbfKernel.QUINTIC: d_quintic_over_r, + RbfKernel.MULTIQUADRIC: d_multiquadric_over_r, + RbfKernel.INVERSE_MULTIQUADRIC: d_inverse_multiquadric_over_r, + RbfKernel.INVERSE_QUADRATIC: d_inverse_quadratic_over_r, + RbfKernel.GAUSSIAN: d_gaussian, + } +) + +KERNEL_SECOND_DERIVATIVE_FUNC = MappingProxyType( + { + RbfKernel.LINEAR: d2_linear, + RbfKernel.CUBIC: d2_cubic, + RbfKernel.THINPLATE: d2_thin_plate_spline, + RbfKernel.QUINTIC: d2_quintic, + RbfKernel.MULTIQUADRIC: d2_multiquadric, + RbfKernel.INVERSE_MULTIQUADRIC: d2_inverse_multiquadric, + RbfKernel.INVERSE_QUADRATIC: d2_inverse_quadratic, + RbfKernel.GAUSSIAN: d2_gaussian, + } +) diff --git a/examples/multiobj/socemo.ipynb b/examples/multiobj/socemo.ipynb index 46ebd721..fef9d4e5 100644 --- a/examples/multiobj/socemo.ipynb +++ b/examples/multiobj/socemo.ipynb @@ -580,8 +580,8 @@ " s[j].update_coefficients(res.fsamples[:i1,j])\n", "\n", " x = np.arange(-100, 100, 0.1).reshape(-1, 1)\n", - " y1 = s[0].eval(x)[0]\n", - " y2 = s[1].eval(x)[0]\n", + " y1 = s[0](x)[0]\n", + " y2 = s[1](x)[0]\n", " fx = objf(x)\n", " f1x = [f[0] for f in fx]\n", " f2x = [f[1] for f in fx]\n", diff --git a/examples/single_obj_rbf/LocalStochRBFstop.py b/examples/single_obj_rbf/LocalStochRBFstop.py index aa8edfaf..9f17ff67 100644 --- a/examples/single_obj_rbf/LocalStochRBFstop.py +++ b/examples/single_obj_rbf/LocalStochRBFstop.py @@ -30,7 +30,7 @@ __deprecated__ = False from optprogram1 import read_check_data_file -from blackboxopt.rbf import RbfType, RbfModel, MedianLpfFilter +from blackboxopt.rbf import RbfKernel, RbfModel, MedianLpfFilter from blackboxopt.optimize import stochastic_response_surface from blackboxopt.sampling import NormalSampler, Sampler, SamplingStrategy from blackboxopt.acquisition import CoordinatePerturbation @@ -48,7 +48,7 @@ NumberNewSamples = 2 data = read_check_data_file(data_file) nCand = 500 * data.dim - phifunction = RbfType.CUBIC + phifunction = RbfKernel.CUBIC m = 2 * (data.dim + 1) numstart = ( 0 # collect all objective function values of the current trial here diff --git a/examples/single_obj_rbf/compareLearningStrategies.py b/examples/single_obj_rbf/compareLearningStrategies.py index 161e1f62..7f6c32b7 100644 --- a/examples/single_obj_rbf/compareLearningStrategies.py +++ b/examples/single_obj_rbf/compareLearningStrategies.py @@ -45,7 +45,7 @@ def read_and_run( maxeval: int = 0, Ntrials: int = 0, NumberNewSamples: int = 0, - rbf_type: rbf.RbfType = rbf.RbfType.CUBIC, + rbf_type: rbf.RbfKernel = rbf.RbfKernel.CUBIC, filter: rbf.RbfFilter = rbf.RbfFilter(), optim_func=optimize.multistart_stochastic_response_surface, ) -> list[optimize.OptimizeResult]: @@ -69,7 +69,7 @@ def read_and_run( Number of trials. NumberNewSamples : int, optional Number of new samples per step of the optimization algorithm. - rbf_type : rbf.RbfType, optional + rbf_type : rbf.RbfKernel, optional Type of RBF to be used. Returns @@ -334,7 +334,7 @@ def check_set_parameters( maxeval=100, Ntrials=3, NumberNewSamples=1, - rbf_type=rbf.RbfType.THINPLATE, + rbf_type=rbf.RbfKernel.THINPLATE, ) if 4 in comparisonList: optresList[4] = read_and_run( @@ -354,7 +354,7 @@ def check_set_parameters( maxeval=100, Ntrials=3, NumberNewSamples=1, - rbf_type=rbf.RbfType.THINPLATE, + rbf_type=rbf.RbfKernel.THINPLATE, optim_func=optimize.stochastic_response_surface, ) if 5 in comparisonList: @@ -366,7 +366,7 @@ def check_set_parameters( maxeval=100, Ntrials=3, NumberNewSamples=1, - rbf_type=rbf.RbfType.THINPLATE, + rbf_type=rbf.RbfKernel.THINPLATE, optim_func=optimize.target_value_optimization, ) if 6 in comparisonList: @@ -388,7 +388,7 @@ def check_set_parameters( maxeval=100, Ntrials=3, NumberNewSamples=1, - rbf_type=rbf.RbfType.THINPLATE, + rbf_type=rbf.RbfKernel.THINPLATE, optim_func=optimize.cptv, ) if 7 in comparisonList: @@ -410,7 +410,7 @@ def check_set_parameters( maxeval=100, Ntrials=3, NumberNewSamples=1, - rbf_type=rbf.RbfType.THINPLATE, + rbf_type=rbf.RbfKernel.THINPLATE, optim_func=optimize.cptvl, ) if 8 in comparisonList: @@ -422,7 +422,7 @@ def check_set_parameters( maxeval=100, Ntrials=3, NumberNewSamples=10, - rbf_type=rbf.RbfType.THINPLATE, + rbf_type=rbf.RbfKernel.THINPLATE, optim_func=optimize.target_value_optimization, ) diff --git a/examples/single_obj_rbf/optprogram1.py b/examples/single_obj_rbf/optprogram1.py index a12c351d..e6e1ff16 100644 --- a/examples/single_obj_rbf/optprogram1.py +++ b/examples/single_obj_rbf/optprogram1.py @@ -57,7 +57,7 @@ def read_and_run( maxeval: int = 0, Ntrials: int = 0, NumberNewSamples: int = 0, - rbf_type: rbf.RbfType = rbf.RbfType.CUBIC, + rbf_type: rbf.RbfKernel = rbf.RbfKernel.CUBIC, filter: rbf.RbfFilter = rbf.RbfFilter(), PlotResult: bool = True, optim_func=optimize.multistart_stochastic_response_surface, @@ -82,7 +82,7 @@ def read_and_run( Number of trials. NumberNewSamples : int, optional Number of new samples per step of the optimization algorithm. - rbf_type : rbf.RbfType, optional + rbf_type : rbf.RbfKernel, optional Type of RBF to be used. PlotResult : bool, optional Plot the results. @@ -366,7 +366,7 @@ def main(args): maxeval=100, Ntrials=3, NumberNewSamples=1, - rbf_type=rbf.RbfType.THINPLATE, + rbf_type=rbf.RbfKernel.THINPLATE, PlotResult=True, ) elif args.config == 4: @@ -387,7 +387,7 @@ def main(args): maxeval=100, Ntrials=3, NumberNewSamples=1, - rbf_type=rbf.RbfType.THINPLATE, + rbf_type=rbf.RbfKernel.THINPLATE, PlotResult=True, optim_func=optimize.stochastic_response_surface, ) @@ -399,7 +399,7 @@ def main(args): maxeval=100, Ntrials=3, NumberNewSamples=1, - rbf_type=rbf.RbfType.THINPLATE, + rbf_type=rbf.RbfKernel.THINPLATE, PlotResult=True, optim_func=optimize.target_value_optimization, ) @@ -421,7 +421,7 @@ def main(args): maxeval=100, Ntrials=3, NumberNewSamples=1, - rbf_type=rbf.RbfType.THINPLATE, + rbf_type=rbf.RbfKernel.THINPLATE, PlotResult=True, optim_func=optimize.cptv, ) @@ -443,7 +443,7 @@ def main(args): maxeval=100, Ntrials=3, NumberNewSamples=1, - rbf_type=rbf.RbfType.THINPLATE, + rbf_type=rbf.RbfKernel.THINPLATE, PlotResult=True, optim_func=optimize.cptvl, ) @@ -455,7 +455,7 @@ def main(args): maxeval=100, Ntrials=3, NumberNewSamples=10, - rbf_type=rbf.RbfType.THINPLATE, + rbf_type=rbf.RbfKernel.THINPLATE, PlotResult=True, optim_func=optimize.target_value_optimization, ) diff --git a/tests/test_rbf.py b/tests/test_rbf.py index 389b328a..94df305d 100644 --- a/tests/test_rbf.py +++ b/tests/test_rbf.py @@ -26,35 +26,33 @@ import numpy as np import sys import pytest -from blackboxopt.rbf import MedianLpfFilter, RbfModel, RbfType +from blackboxopt.rbf import MedianLpfFilter, RbfModel +from blackboxopt.rbf_kernel import linear, cubic, thin_plate_spline class TestRbfModel: rbf_model = RbfModel() def test_phi(self): - self.rbf_model.type = RbfType.LINEAR r_linear = np.array([1.0, 2.0, 3.0]) - result_linear = self.rbf_model.phi(r_linear) - expected_linear = np.array([1.0, 2.0, 3.0]) + result_linear = linear(r_linear) + expected_linear = -np.array([1.0, 2.0, 3.0]) np.testing.assert_array_equal(np.array(result_linear), expected_linear) - assert self.rbf_model.phi(4.0) == 4.0 + assert linear(4.0) == -4.0 - self.rbf_model.type = RbfType.CUBIC r_cubic = np.array([1.0, 2.0, 3.0]) - result_cubic = self.rbf_model.phi(r_cubic) + result_cubic = cubic(r_cubic) expected_cubic = np.array([1.0, 8.0, 27.0]) np.testing.assert_array_equal(np.array(result_cubic), expected_cubic) - assert self.rbf_model.phi(4.0) == 64.0 + assert cubic(4.0) == 64.0 - self.rbf_model.type = RbfType.THINPLATE r_thinplate = np.array([1.0, 2.0, 3.0]) - result_thinplate = self.rbf_model.phi(r_thinplate) + result_thinplate = thin_plate_spline(r_thinplate) expected_thinplate = np.array([0.0, 2.77258872, 9.8875106]) np.testing.assert_allclose( np.array(result_thinplate), expected_thinplate ) - assert self.rbf_model.phi(4.0) == ( + assert thin_plate_spline(4.0) == ( 4 * 4 * np.log(4 + sys.float_info.min) ) diff --git a/tests/test_vlse_bench.py b/tests/test_vlse_bench.py index 747d1b0c..06df1f95 100644 --- a/tests/test_vlse_bench.py +++ b/tests/test_vlse_bench.py @@ -139,7 +139,7 @@ def objf(x: np.ndarray) -> np.ndarray: # Surrogate model with median low-pass filter rbfModel = rbf.RbfModel( - rbf.RbfType.CUBIC, iindex, filter=rbf.MedianLpfFilter() + rbf.RbfKernel.CUBIC, iindex, filter=rbf.MedianLpfFilter() ) # Update acquisition strategy, using maxEval and nArgs for the problem From c7c1eec227eb8e5ed07b73a11313626efd28d7c7 Mon Sep 17 00:00:00 2001 From: Weslley da Silva Pereira Date: Fri, 28 Jun 2024 16:00:48 -0600 Subject: [PATCH 14/24] Fix bug in the target_value_optimization --- blackboxopt/optimize.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/blackboxopt/optimize.py b/blackboxopt/optimize.py index c6bc4416..5f535a87 100644 --- a/blackboxopt/optimize.py +++ b/blackboxopt/optimize.py @@ -898,7 +898,11 @@ def target_value_optimization( # max value of f if surrogateModel.nsamples() - out.nfev > 0: - maxf = np.max(surrogateModel.get_fsamples()[: -out.nfev]).item() + maxf = np.max( + surrogateModel.get_fsamples()[ + 0 : surrogateModel.nsamples() - out.nfev + ] + ).item() else: maxf = -np.Inf if out.nfev > 0: From 4e76af21f5c8679926d90367ce0f0eeab98b9a92 Mon Sep 17 00:00:00 2001 From: Weslley da Silva Pereira Date: Fri, 28 Jun 2024 16:57:19 -0600 Subject: [PATCH 15/24] Adds smoothing parameter as an option to the RBF model --- blackboxopt/rbf.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/blackboxopt/rbf.py b/blackboxopt/rbf.py index 85433c2c..fdcd4759 100644 --- a/blackboxopt/rbf.py +++ b/blackboxopt/rbf.py @@ -130,10 +130,12 @@ class RbfModel: def __init__( self, + smoothing: float = 0.0, kernel: RbfKernel = RbfKernel.CUBIC, iindex: tuple[int, ...] = (), filter: Optional[RbfFilter] = None, ): + self.smoothing = smoothing self.iindex = iindex self.filter = RbfFilter() if filter is None else filter @@ -588,7 +590,11 @@ def get_RBFmatrix(self) -> np.ndarray: pdim = self.pdim() return np.block( [ - [self._PHI[0 : self._m, 0 : self._m], self.get_matrixP()], + [ + self._PHI[0 : self._m, 0 : self._m] + + self.smoothing * np.eye(self._m), + self.get_matrixP(), + ], [self.get_matrixP().T, np.zeros((pdim, pdim))], ] ) From 8df0af00b0e65619d369f68ff26d60e318f2ca2d Mon Sep 17 00:00:00 2001 From: Weslley da Silva Pereira Date: Fri, 28 Jun 2024 18:45:39 -0600 Subject: [PATCH 16/24] Adds scaling of ranges to improve conditioning --- blackboxopt/acquisition.py | 2 +- blackboxopt/rbf.py | 115 ++++++++++++++---- examples/single_obj_rbf/LocalStochRBFstop.py | 2 +- .../compareLearningStrategies.py | 4 +- examples/single_obj_rbf/optprogram1.py | 4 +- tests/test_vlse_bench.py | 2 +- 6 files changed, 100 insertions(+), 29 deletions(-) diff --git a/blackboxopt/acquisition.py b/blackboxopt/acquisition.py index 247504e8..9d718ffe 100644 --- a/blackboxopt/acquisition.py +++ b/blackboxopt/acquisition.py @@ -1015,7 +1015,7 @@ def pareto_front_target(self, paretoFront: np.ndarray) -> np.ndarray: assert objdim > 1 # Create a surrogate model for the Pareto front in the objective space - paretoModel = RbfModel(RbfKernel.LINEAR) + paretoModel = RbfModel(kernel=RbfKernel.LINEAR) k = np.random.choice(objdim) paretoModel.update_samples( np.array([paretoFront[:, i] for i in range(objdim) if i != k]).T diff --git a/blackboxopt/rbf.py b/blackboxopt/rbf.py index fdcd4759..353fbe7b 100644 --- a/blackboxopt/rbf.py +++ b/blackboxopt/rbf.py @@ -130,6 +130,7 @@ class RbfModel: def __init__( self, + *, smoothing: float = 0.0, kernel: RbfKernel = RbfKernel.CUBIC, iindex: tuple[int, ...] = (), @@ -159,6 +160,10 @@ def __init__( self._P = np.array([]) self._POWERS = np.array([], dtype=np.dtype("long")) + self._scale = np.array([]) + self._avg = np.array([]) + self._change_scale_factor = 2.0 # Change the scale factor when new scale is 2 times larger than the current one + def reserve(self, maxeval: int, dim: int) -> None: """Reserve space for the RBF model. @@ -340,10 +345,14 @@ def __call__(self, x: np.ndarray) -> tuple[np.ndarray, np.ndarray]: dim = self.dim() phi = KERNEL_FUNC[self._kernel] + # Scale x and samples + xscaled = (x.reshape(-1, dim) - self._avg) / self._scale + sscaled = (self.samples() - self._avg) / self._scale + # compute pairwise distances between candidates and sampled points - D = cdist(x.reshape(-1, dim), self.samples()) + D = cdist(xscaled, sscaled) - Px = self.pbasis(x) + Px = self.pbasis(xscaled) y = np.matmul(phi(D), self._coef[0 : self._m]) + np.dot( Px, self._coef[self._m : self._m + Px.shape[1]] ) @@ -376,11 +385,18 @@ def jac(self, x: np.ndarray) -> np.ndarray: dim = self.dim() dphiOverR = KERNEL_DERIVATIVE_OVER_R_FUNC[self._kernel] + # Scale x and samples + xscaled = (x.reshape(-1, dim) - self._avg) / self._scale + sscaled = (self.samples() - self._avg) / self._scale + # compute pairwise distances between candidates and sampled points - d = cdist(x.reshape(-1, dim), self.samples()).flatten() + d = cdist(xscaled, sscaled).flatten() - A = np.array([dphiOverR(d[i]) * x for i in range(d.size)]) - B = self.dpbasis(x) + A = np.matmul( + np.array([dphiOverR(d[i]) * xscaled for i in range(d.size)]), + np.diag(1 / self._scale), + ) + B = np.matmul(np.diag(1 / self._scale), self.dpbasis(xscaled)) y = np.matmul(A.T, self._coef[0 : self._m]) + np.matmul( B, self._coef[self._m : self._m + B.shape[1]] @@ -449,28 +465,69 @@ def update_samples(self, xNew: np.ndarray, distNew=None) -> None: newm = xNew.shape[0] dim = xNew.shape[1] m = oldm + newm + phi = KERNEL_FUNC[self._kernel] if oldm > 0: assert dim == self.dim() if newm == 0: return - # Compute distances between new points and sampled points - if distNew is None: - if oldm == 0: - distNew = cdist(xNew, xNew) - else: - distNew = cdist( - xNew, np.concatenate((self.samples(), xNew), axis=0) - ) + # Compute new scaling factor + if len(self._scale) > 0: + xmax = np.max( + np.concatenate((xNew, self.samples()), axis=0), axis=0 + ) + xmin = np.min( + np.concatenate((xNew, self.samples()), axis=0), axis=0 + ) + new_scale = (xmax - xmin) / 2 + new_scale = np.where(new_scale == 0, 1, new_scale) + else: + xmax = np.max(xNew, axis=0) + xmin = np.min(xNew, axis=0) + new_scale = (xmax - xmin) / 2 + new_scale = np.where(new_scale == 0, 1, new_scale) + self._scale = new_scale + self._avg = (xmax + xmin) / 2 + + if len(self._scale) == 0 or np.all( + new_scale < self._scale * self._change_scale_factor + ): + # Scale points + xscaled = (xNew - self._avg) / self._scale + + # Compute distances between new points and sampled points + if distNew is None: + if oldm == 0: + distNew = cdist(xscaled, xscaled) + else: + sscaled = (self.samples() - self._avg) / self._scale + distNew = cdist( + xscaled, + np.concatenate((sscaled, xscaled), axis=0), + ) - self.reserve(m, dim) + self.reserve(m, dim) - # Update matrices _PHI and _P - phi = KERNEL_FUNC[self._kernel] - self._PHI[oldm:m, 0:m] = phi(distNew) - self._PHI[0:oldm, oldm:m] = self._PHI[oldm:m, 0:oldm].T - self._P[oldm:m, :] = self.pbasis(xNew) + # Update matrices _PHI and _P + self._PHI[oldm:m, 0:m] = phi(distNew) + self._PHI[0:oldm, oldm:m] = self._PHI[oldm:m, 0:oldm].T + self._P[oldm:m, :] = self.pbasis(xscaled) + else: + # Update scaling factor + self._scale = new_scale + self._avg = (xmax + xmin) / 2 + + # Scale points + xscaled = np.concatenate((self.samples(), xNew), axis=0) + xscaled = (xscaled - self._avg) / self._scale + + # Recompute distances between sampled points + distNew = cdist(xscaled, xscaled) + + # Update matrices _PHI and _P + self._PHI[0:m, 0:m] = phi(distNew) + self._P[0:m, :] = self.pbasis(xscaled) # Update x self._x[oldm:m, :] = xNew @@ -524,13 +581,21 @@ def create_initial_design( if count > 100: raise RuntimeError("Cannot create valid initial design") + # Compute scaling factor + xmax = np.max(self.samples(), axis=0) + xmin = np.min(self.samples(), axis=0) + self._scale = (xmax - xmin) / 2 + self._scale = np.where(self._scale == 0, 1, self._scale) + self._avg = (xmax + xmin) / 2 + # Compute distances between new points and sampled points - distNew = cdist(self.samples(), self.samples()) + xscaled = (self.samples() - self._avg) / self._scale + distNew = cdist(xscaled, xscaled) - # Set matrix _PHI + # Set matrices _PHI and _P phi = KERNEL_FUNC[self._kernel] self._PHI[0:m, 0:m] = phi(distNew) - self._PHI[0:0, 0:m] = self._PHI[0:m, 0:0].T + self._P[0:m, :] = self.pbasis(xscaled) # Coefficients are not valid self._valid_coefficients = False @@ -643,10 +708,12 @@ def mu_measure(self, x: np.ndarray, xdist=None, LDLt=()) -> float: phi = KERNEL_FUNC[self._kernel] # compute rbf value of the new point x + xscaled = (x - self._avg) / self._scale + sscaled = (self.samples() - self._avg) / self._scale if xdist is None: - xdist = cdist(x.reshape(1, -1), self.samples()) + xdist = cdist(xscaled.reshape(1, -1), sscaled) newRow = np.concatenate( - (np.asarray(phi(xdist)).flatten(), self.pbasis(x).flatten()) + (np.asarray(phi(xdist)).flatten(), self.pbasis(xscaled).flatten()) ) if LDLt: diff --git a/examples/single_obj_rbf/LocalStochRBFstop.py b/examples/single_obj_rbf/LocalStochRBFstop.py index 9f17ff67..75e6dde1 100644 --- a/examples/single_obj_rbf/LocalStochRBFstop.py +++ b/examples/single_obj_rbf/LocalStochRBFstop.py @@ -94,7 +94,7 @@ print(samples) print("LocalStochRBFstop Start") - rbfModel = RbfModel(phifunction, filter=MedianLpfFilter()) + rbfModel = RbfModel(kernel=phifunction, filter=MedianLpfFilter()) optres = stochastic_response_surface( data.objfunction, diff --git a/examples/single_obj_rbf/compareLearningStrategies.py b/examples/single_obj_rbf/compareLearningStrategies.py index 7f6c32b7..3fb6daec 100644 --- a/examples/single_obj_rbf/compareLearningStrategies.py +++ b/examples/single_obj_rbf/compareLearningStrategies.py @@ -88,7 +88,9 @@ def read_and_run( optres = [] for j in range(Ntrials): # Create empty RBF model - rbfModel = rbf.RbfModel(rbf_type, data.iindex, filter=filter) + rbfModel = rbf.RbfModel( + kernel=rbf_type, iindex=data.iindex, filter=filter + ) acquisitionFuncIter = deepcopy(acquisitionFunc) # # Uncomment to compare with Surrogates.jl diff --git a/examples/single_obj_rbf/optprogram1.py b/examples/single_obj_rbf/optprogram1.py index e6e1ff16..a4eb54ff 100644 --- a/examples/single_obj_rbf/optprogram1.py +++ b/examples/single_obj_rbf/optprogram1.py @@ -103,7 +103,9 @@ def read_and_run( optres = [] for j in range(Ntrials): # Create empty RBF model - rbfModel = rbf.RbfModel(rbf_type, data.iindex, filter=filter) + rbfModel = rbf.RbfModel( + kernel=rbf_type, iindex=data.iindex, filter=filter + ) acquisitionFuncIter = deepcopy(acquisitionFunc) # # Uncomment to compare with Surrogates.jl diff --git a/tests/test_vlse_bench.py b/tests/test_vlse_bench.py index 06df1f95..e6c438ea 100644 --- a/tests/test_vlse_bench.py +++ b/tests/test_vlse_bench.py @@ -139,7 +139,7 @@ def objf(x: np.ndarray) -> np.ndarray: # Surrogate model with median low-pass filter rbfModel = rbf.RbfModel( - rbf.RbfKernel.CUBIC, iindex, filter=rbf.MedianLpfFilter() + kernel=rbf.RbfKernel.CUBIC, iindex=iindex, filter=rbf.MedianLpfFilter() ) # Update acquisition strategy, using maxEval and nArgs for the problem From eb553b15351857964fd8322b55c805885acd9b66 Mon Sep 17 00:00:00 2001 From: Weslley da Silva Pereira Date: Tue, 9 Jul 2024 11:46:56 -0600 Subject: [PATCH 17/24] Adds epsilon param to complete kernels --- blackboxopt/rbf.py | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/blackboxopt/rbf.py b/blackboxopt/rbf.py index 353fbe7b..c6e61326 100644 --- a/blackboxopt/rbf.py +++ b/blackboxopt/rbf.py @@ -119,8 +119,18 @@ class RbfModel: Attributes ---------- - type : RbfKernel, optional - Defines the function phi used in the RBF model. The options are listed in the RbfKernel enum. + smoothing : float, optional + Smoothing parameter. The interpolant perfectly fits the data when this + is set to 0. For large values, the interpolant approaches a least + squares fit of a polynomial with the specified degree. Default is 0. + kernel : RbfKernel, optional + Defines the function phi used in the RBF model. The options are listed + in the RbfKernel enum. + epsilon : float, optional + Shape parameter that scales the input to the RBF. If `kernel` is + 'linear', 'thin_plate_spline', 'cubic', or 'quintic', this defaults to + 1 and can be ignored because it has the same effect as scaling the + smoothing parameter. Defaults to 1. iindex : tuple, optional Indices of the input space that are integer. The default is (). filter : RbfFilter, optional @@ -133,12 +143,14 @@ def __init__( *, smoothing: float = 0.0, kernel: RbfKernel = RbfKernel.CUBIC, + epsilon: float = 1.0, iindex: tuple[int, ...] = (), filter: Optional[RbfFilter] = None, ): self.smoothing = smoothing self.iindex = iindex self.filter = RbfFilter() if filter is None else filter + self.epsilon = epsilon # Set kernel and the degree of the polynomial tail self._kernel = kernel @@ -350,7 +362,7 @@ def __call__(self, x: np.ndarray) -> tuple[np.ndarray, np.ndarray]: sscaled = (self.samples() - self._avg) / self._scale # compute pairwise distances between candidates and sampled points - D = cdist(xscaled, sscaled) + D = cdist(xscaled, sscaled) * self.epsilon Px = self.pbasis(xscaled) y = np.matmul(phi(D), self._coef[0 : self._m]) + np.dot( @@ -510,7 +522,7 @@ def update_samples(self, xNew: np.ndarray, distNew=None) -> None: self.reserve(m, dim) # Update matrices _PHI and _P - self._PHI[oldm:m, 0:m] = phi(distNew) + self._PHI[oldm:m, 0:m] = phi(distNew * self.epsilon) self._PHI[0:oldm, oldm:m] = self._PHI[oldm:m, 0:oldm].T self._P[oldm:m, :] = self.pbasis(xscaled) else: @@ -526,7 +538,7 @@ def update_samples(self, xNew: np.ndarray, distNew=None) -> None: distNew = cdist(xscaled, xscaled) # Update matrices _PHI and _P - self._PHI[0:m, 0:m] = phi(distNew) + self._PHI[0:m, 0:m] = phi(distNew * self.epsilon) self._P[0:m, :] = self.pbasis(xscaled) # Update x @@ -594,7 +606,7 @@ def create_initial_design( # Set matrices _PHI and _P phi = KERNEL_FUNC[self._kernel] - self._PHI[0:m, 0:m] = phi(distNew) + self._PHI[0:m, 0:m] = phi(distNew * self.epsilon) self._P[0:m, :] = self.pbasis(xscaled) # Coefficients are not valid @@ -713,7 +725,10 @@ def mu_measure(self, x: np.ndarray, xdist=None, LDLt=()) -> float: if xdist is None: xdist = cdist(xscaled.reshape(1, -1), sscaled) newRow = np.concatenate( - (np.asarray(phi(xdist)).flatten(), self.pbasis(xscaled).flatten()) + ( + np.asarray(phi(xdist * self.epsilon)).flatten(), + self.pbasis(xscaled).flatten(), + ) ) if LDLt: From 937e90bf5dee092925ffa0d2bde02151206b8e40 Mon Sep 17 00:00:00 2001 From: Weslley da Silva Pereira Date: Tue, 9 Jul 2024 17:16:10 -0600 Subject: [PATCH 18/24] Fixes bugs in the mu meas and jac of RBF --- blackboxopt/acquisition.py | 6 +++--- blackboxopt/rbf.py | 25 ++++++++++++++++++++----- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/blackboxopt/acquisition.py b/blackboxopt/acquisition.py index 9d718ffe..86f2b1f2 100644 --- a/blackboxopt/acquisition.py +++ b/blackboxopt/acquisition.py @@ -601,7 +601,7 @@ def acquire( else np.random.choice(self.cycleLength + 2) ) if sample_stage == 0: # InfStep - minimize Mu_n - LDLt = ldl(surrogateModel.get_RBFmatrix()) + LDLt = ldl(surrogateModel.get_RBFmatrix(smoothing=0)) problem = ProblemWithConstraint( lambda x: surrogateModel.mu_measure(x, LDLt=LDLt), lambda x: self.tol @@ -657,7 +657,7 @@ def acquire( ) # target for objective function value # use GA method to minimize bumpiness measure - LDLt = ldl(surrogateModel.get_RBFmatrix()) + LDLt = ldl(surrogateModel.get_RBFmatrix(smoothing=0)) problem = ProblemWithConstraint( lambda x: surrogateModel.bumpiness_measure( x, f_target, LDLt @@ -723,7 +723,7 @@ def acquire( fbounds[0] ) # target value # use GA method to minimize bumpiness measure - LDLt = ldl(surrogateModel.get_RBFmatrix()) + LDLt = ldl(surrogateModel.get_RBFmatrix(smoothing=0)) problem = ProblemWithConstraint( lambda x: surrogateModel.bumpiness_measure( x, f_target, LDLt diff --git a/blackboxopt/rbf.py b/blackboxopt/rbf.py index c6e61326..c4fc801e 100644 --- a/blackboxopt/rbf.py +++ b/blackboxopt/rbf.py @@ -405,8 +405,13 @@ def jac(self, x: np.ndarray) -> np.ndarray: d = cdist(xscaled, sscaled).flatten() A = np.matmul( - np.array([dphiOverR(d[i]) * xscaled for i in range(d.size)]), - np.diag(1 / self._scale), + np.array( + [ + dphiOverR(d[i] * self.epsilon) * xscaled + for i in range(d.size) + ] + ), + np.diag(self.epsilon / self._scale), ) B = np.matmul(np.diag(1 / self._scale), self.dpbasis(xscaled)) @@ -656,20 +661,30 @@ def get_matrixP(self) -> np.ndarray: """ return self._P[0 : self._m, :] - def get_RBFmatrix(self) -> np.ndarray: + def get_RBFmatrix( + self, *, smoothing: Optional[float] = None + ) -> np.ndarray: """Get the matrix used to compute the RBF weights. + Parameters + ---------- + smoothing : float, optional + Smoothing parameter, if different from the one used in the model. + Returns ------- out: np.ndarray (m+pdim)-by-(m+pdim) matrix used to compute the RBF weights. """ + if smoothing is None: + smoothing = self.smoothing + pdim = self.pdim() return np.block( [ [ self._PHI[0 : self._m, 0 : self._m] - + self.smoothing * np.eye(self._m), + + smoothing * np.eye(self._m), self.get_matrixP(), ], [self.get_matrixP().T, np.zeros((pdim, pdim))], @@ -773,7 +788,7 @@ def mu_measure(self, x: np.ndarray, xdist=None, LDLt=()) -> float: # set up matrices for solving the linear system A_aug = np.block( [ - [self.get_RBFmatrix(), newRow.reshape(-1, 1)], + [self.get_RBFmatrix(smoothing=0), newRow.reshape(-1, 1)], [newRow, phi(0)], ] ) From ee17caaca8204d25628b45bd89538698adf92bf7 Mon Sep 17 00:00:00 2001 From: Weslley da Silva Pereira Date: Tue, 9 Jul 2024 17:37:08 -0600 Subject: [PATCH 19/24] Revert f4b4c105dce5d26e00f3135fc88e7051c518fe4e --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index 5104c463..2ad941c0 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,6 @@ Surrogate models and active learning for scientific applications. -__This repository was moved to https://github.com/NREL/bbopt__ - ## Building This project uses [pdm](https://pdm-project.org/en/stable/) as its package manager. With pdm installed, run `pdm install` at the root of this repository to install the dependencies. The file [pyproject.toml](pyproject.toml) has the list of dependencies and configurations for the project. Use `pdm build` to build the project. The build artifacts will be in the `dist` directory. Please, find more information about pdm in its website. @@ -26,4 +24,4 @@ This project is licensed under the GPL-3.0 License. See the [LICENSE](LICENSE) f --- -_NREL Software Record number: SWR-24-57_ +_NREL Software Record number: SWR-24-57_ \ No newline at end of file From 10b019dc86cccd414d691de752cb1774d9689f9d Mon Sep 17 00:00:00 2001 From: "Weslley S. Pereira" Date: Thu, 11 Jul 2024 09:26:25 -0600 Subject: [PATCH 20/24] Create dir if doesnt exist in vlse_bench --- examples/vlse_benchmark/vlse_bench.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/examples/vlse_benchmark/vlse_bench.py b/examples/vlse_benchmark/vlse_bench.py index d9c28816..3aef93ef 100644 --- a/examples/vlse_benchmark/vlse_bench.py +++ b/examples/vlse_benchmark/vlse_bench.py @@ -29,6 +29,7 @@ import time from tests.test_vlse_bench import run_optimizer from blackboxopt import optimize, acquisition, sampling +from pathlib import Path # Functions to be tested myRfuncs = ( @@ -198,9 +199,11 @@ tf = time.time() # Save the results + folder = os.path.dirname(os.path.abspath(__file__)) + "/pickle" + Path(folder).mkdir(parents=True, exist_ok=True) filepath = ( - os.path.dirname(os.path.abspath(__file__)) - + "/pickle/vlse_bench_plot_" + folder + + "/" + args.problem + "_" + args.algorithm From 91e7a0acb2c422da8833cfd2df5414e2eabd37b6 Mon Sep 17 00:00:00 2001 From: Weslley da Silva Pereira Date: Thu, 11 Jul 2024 09:50:53 -0600 Subject: [PATCH 21/24] Adds more tests to RBF and improve docs --- blackboxopt/rbf.py | 53 +++++++++++++++++++++++++---------------- tests/test_rbf.py | 59 ++++++++++++++++++++++++++-------------------- 2 files changed, 67 insertions(+), 45 deletions(-) diff --git a/blackboxopt/rbf.py b/blackboxopt/rbf.py index ed16dc24..f66a9ed9 100644 --- a/blackboxopt/rbf.py +++ b/blackboxopt/rbf.py @@ -123,14 +123,6 @@ class RbfModel: Smoothing parameter. The interpolant perfectly fits the data when this is set to 0. For large values, the interpolant approaches a least squares fit of a polynomial with the specified degree. Default is 0. - kernel : RbfKernel, optional - Defines the function phi used in the RBF model. The options are listed - in the RbfKernel enum. - epsilon : float, optional - Shape parameter that scales the input to the RBF. If `kernel` is - 'linear', 'thin_plate_spline', 'cubic', or 'quintic', this defaults to - 1 and can be ignored because it has the same effect as scaling the - smoothing parameter. Defaults to 1. iindex : tuple, optional Indices of the input space that are integer. The default is (). filter : RbfFilter, optional @@ -147,10 +139,34 @@ def __init__( iindex: tuple[int, ...] = (), filter: Optional[RbfFilter] = None, ): + """Initialize the RBF model + + By default, the model uses a cubic kernel with no smoothing. + + Parameters + ---------- + smoothing : float, optional + Smoothing parameter. The interpolant perfectly fits the data when this + is set to 0. For large values, the interpolant approaches a least + squares fit of a polynomial with the specified degree. Default is 0. + kernel : RbfKernel + Defines the function phi used in the RBF model. The options are listed + in the RbfKernel enum. + epsilon : float, optional + Shape parameter that scales the input to the RBF. If `kernel` is + 'linear', 'thin_plate_spline', 'cubic', or 'quintic', this defaults to + 1 and can be ignored because it has the same effect as scaling the + smoothing parameter. Defaults to 1. + iindex : tuple, optional + Indices of the input space that are integer. The default is (). + filter : RbfFilter, optional + Filter used with the function values. The default is RbfFilter() which + is the identity function. + """ + self.smoothing = smoothing self.iindex = iindex self.filter = RbfFilter() if filter is None else filter - self.epsilon = epsilon # Set kernel and the degree of the polynomial tail self._kernel = kernel @@ -162,6 +178,7 @@ def __init__( self._degree = 2 else: self._degree = None + self._eps = epsilon self._valid_coefficients = True self._m = 0 @@ -170,7 +187,6 @@ def __init__( self._coef = np.array([]) self._PHI = np.array([]) self._P = np.array([]) - self._POWERS = np.array([], dtype=np.dtype("long")) self._scale = np.array([]) self._avg = np.array([]) @@ -362,7 +378,7 @@ def __call__(self, x: np.ndarray) -> tuple[np.ndarray, np.ndarray]: sscaled = (self.samples() - self._avg) / self._scale # compute pairwise distances between candidates and sampled points - D = cdist(xscaled, sscaled) * self.epsilon + D = cdist(xscaled, sscaled) * self._eps Px = self.pbasis(xscaled) y = np.matmul(phi(D), self._coef[0 : self._m]) + np.dot( @@ -406,12 +422,9 @@ def jac(self, x: np.ndarray) -> np.ndarray: A = np.matmul( np.array( - [ - dphiOverR(d[i] * self.epsilon) * xscaled - for i in range(d.size) - ] + [dphiOverR(d[i] * self._eps) * xscaled for i in range(d.size)] ), - np.diag(self.epsilon / self._scale), + np.diag(self._eps / self._scale), ) B = np.matmul(np.diag(1 / self._scale), self.dpbasis(xscaled)) @@ -527,7 +540,7 @@ def update_samples(self, xNew: np.ndarray, distNew=None) -> None: self.reserve(m, dim) # Update matrices _PHI and _P - self._PHI[oldm:m, 0:m] = phi(distNew * self.epsilon) + self._PHI[oldm:m, 0:m] = phi(distNew * self._eps) self._PHI[0:oldm, oldm:m] = self._PHI[oldm:m, 0:oldm].T self._P[oldm:m, :] = self.pbasis(xscaled) else: @@ -543,7 +556,7 @@ def update_samples(self, xNew: np.ndarray, distNew=None) -> None: distNew = cdist(xscaled, xscaled) # Update matrices _PHI and _P - self._PHI[0:m, 0:m] = phi(distNew * self.epsilon) + self._PHI[0:m, 0:m] = phi(distNew * self._eps) self._P[0:m, :] = self.pbasis(xscaled) # Update x @@ -611,7 +624,7 @@ def create_initial_design( # Set matrices _PHI and _P phi = KERNEL_FUNC[self._kernel] - self._PHI[0:m, 0:m] = phi(distNew * self.epsilon) + self._PHI[0:m, 0:m] = phi(distNew * self._eps) self._P[0:m, :] = self.pbasis(xscaled) # Coefficients are not valid @@ -741,7 +754,7 @@ def mu_measure(self, x: np.ndarray, xdist=None, LDLt=()) -> float: xdist = cdist(xscaled.reshape(1, -1), sscaled) newRow = np.concatenate( ( - np.asarray(phi(xdist * self.epsilon)).flatten(), + np.asarray(phi(xdist * self._eps)).flatten(), self.pbasis(xscaled).flatten(), ) ) diff --git a/tests/test_rbf.py b/tests/test_rbf.py index 94df305d..c4adbd93 100644 --- a/tests/test_rbf.py +++ b/tests/test_rbf.py @@ -24,38 +24,47 @@ __deprecated__ = False import numpy as np -import sys import pytest from blackboxopt.rbf import MedianLpfFilter, RbfModel -from blackboxopt.rbf_kernel import linear, cubic, thin_plate_spline +from blackboxopt.rbf_kernel import RbfKernel, KERNEL_FUNC + + +@pytest.mark.parametrize("kernel", [k for k in RbfKernel]) +def test_kernel(kernel): + testInput = [1.0, 2.0, 3.0, 4.0] + testResults = { + RbfKernel.LINEAR: [-1.0, -2.0, -3.0, -4.0], + RbfKernel.CUBIC: [1.0, 8.0, 27.0, 64.0], + RbfKernel.THINPLATE: [0.0, 2.7725887, 9.88751, 22.18071], + RbfKernel.QUINTIC: [-1.0, -32.0, -243.0, -1024.0], + RbfKernel.MULTIQUADRIC: [ + -1.4142135, + -2.236068, + -3.1622777, + -4.1231055, + ], + RbfKernel.INVERSE_MULTIQUADRIC: [ + 0.70710677, + 0.4472136, + 0.31622776, + 0.24253562, + ], + RbfKernel.INVERSE_QUADRATIC: [0.5, 0.2, 0.1, 0.05882353], + RbfKernel.GAUSSIAN: [ + 3.67879450e-01, + 1.83156393e-02, + 1.23409802e-04, + 1.12535176e-07, + ], + } + phi = KERNEL_FUNC[kernel] + + np.testing.assert_array_almost_equal(phi(testInput), testResults[kernel]) class TestRbfModel: rbf_model = RbfModel() - def test_phi(self): - r_linear = np.array([1.0, 2.0, 3.0]) - result_linear = linear(r_linear) - expected_linear = -np.array([1.0, 2.0, 3.0]) - np.testing.assert_array_equal(np.array(result_linear), expected_linear) - assert linear(4.0) == -4.0 - - r_cubic = np.array([1.0, 2.0, 3.0]) - result_cubic = cubic(r_cubic) - expected_cubic = np.array([1.0, 8.0, 27.0]) - np.testing.assert_array_equal(np.array(result_cubic), expected_cubic) - assert cubic(4.0) == 64.0 - - r_thinplate = np.array([1.0, 2.0, 3.0]) - result_thinplate = thin_plate_spline(r_thinplate) - expected_thinplate = np.array([0.0, 2.77258872, 9.8875106]) - np.testing.assert_allclose( - np.array(result_thinplate), expected_thinplate - ) - assert thin_plate_spline(4.0) == ( - 4 * 4 * np.log(4 + sys.float_info.min) - ) - def test_dim(self): assert self.rbf_model.dim() == 0 From cdeed1f4b67aff8f8e83314f749c01402b43f498 Mon Sep 17 00:00:00 2001 From: Weslley da Silva Pereira Date: Thu, 11 Jul 2024 09:56:17 -0600 Subject: [PATCH 22/24] Be more flexible in the GOSAC benchmark. Delete wrong known info --- tests/gosac_benchmark.py | 36 ++++++++++++++++++------------------ tests/test_gosac_bench.py | 31 ++++++++++++++++--------------- 2 files changed, 34 insertions(+), 33 deletions(-) diff --git a/tests/gosac_benchmark.py b/tests/gosac_benchmark.py index 9ddeb0bc..66b9ab03 100644 --- a/tests/gosac_benchmark.py +++ b/tests/gosac_benchmark.py @@ -419,8 +419,8 @@ class Problem: lambda x: np.reshape(fRana(x) - 5, (-1, 1)), (0,), ((-9, 9), (-3 * np.pi, 3 * np.pi)), - (-8, -9.4142), - -104.3309, + # (-8, -9.4142), + # -104.3309, ) ) @@ -487,20 +487,20 @@ class Problem: # Problem 16 gosac_p.append(copy(gosac_p[3])) gosac_p[-1].iindex = () -gosac_p[-1].xmin = ( - 0.4849, - 0.8024, - 0.4851, - 0.0690, - 0.4849, - 0.8024, - 0.4851, - 0.9690, - 0.2310, - 0.9976, - 1.9990, -) -gosac_p[-1].fmin = 3.8853 +# gosac_p[-1].xmin = ( +# 0.4849, +# 0.8024, +# 0.4851, +# 0.0690, +# 0.4849, +# 0.8024, +# 0.4851, +# 0.9690, +# 0.2310, +# 0.9976, +# 1.9990, +# ) +# gosac_p[-1].fmin = 3.8853 # Problem 17 gosac_p.append(copy(gosac_p[2])) @@ -700,8 +700,8 @@ class Problem: lambda x: np.reshape(-np.sum(np.sin(10 * np.log(x)), axis=1), (-1, 1)), (), ((0.25, np.pi),) * 10, - (3, 2, 3, 2, 3, 2, 3, 3, 1, 2), - 1.1783, + # (3, 2, 3, 2, 3, 2, 3, 3, 1, 2), + # 1.1783, ) ) diff --git a/tests/test_gosac_bench.py b/tests/test_gosac_bench.py index 3a98a0fc..69fe0b1b 100644 --- a/tests/test_gosac_bench.py +++ b/tests/test_gosac_bench.py @@ -54,21 +54,22 @@ def test_gosac(problem: gosacbmk.Problem) -> None: @pytest.mark.parametrize("problem", gosacbmk.gosac_p) def test_benchmark(problem: gosacbmk.Problem) -> None: - print(problem.xmin) - print(problem.fmin) - print(problem.objf(np.asarray([problem.xmin]))[0]) - print(problem.gfun(np.asarray([problem.xmin]))[0]) - - if problem.fmin is not None and problem.fmin != 0: - assert ( - abs(problem.objf(np.asarray([problem.xmin]))[0] - problem.fmin) - / abs(problem.fmin) - <= 1e-3 - ) - else: - assert problem.objf(np.asarray([problem.xmin]))[0] == problem.fmin - - assert np.all(problem.gfun(np.asarray([problem.xmin]))[0] <= 0) + if problem.xmin is not None and problem.fmin is not None: + print(problem.xmin) + print(problem.fmin) + print(problem.objf(np.asarray([problem.xmin]))[0]) + print(problem.gfun(np.asarray([problem.xmin]))[0]) + + if problem.fmin != 0: + assert ( + abs(problem.objf(np.asarray([problem.xmin]))[0] - problem.fmin) + / abs(problem.fmin) + <= 1e-2 + ) + else: + assert problem.objf(np.asarray([problem.xmin]))[0] == problem.fmin + + assert np.all(problem.gfun(np.asarray([problem.xmin]))[0] <= 1e-2) if __name__ == "__main__": From 2997278de234a485def69cb5e55cf4f02b02b44b Mon Sep 17 00:00:00 2001 From: Weslley da Silva Pereira Date: Wed, 14 Aug 2024 09:43:33 -0600 Subject: [PATCH 23/24] Avoids recomputing scaled x by keeping it as an attribute --- blackboxopt/rbf.py | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/blackboxopt/rbf.py b/blackboxopt/rbf.py index f66a9ed9..28fb0626 100644 --- a/blackboxopt/rbf.py +++ b/blackboxopt/rbf.py @@ -188,6 +188,8 @@ def __init__( self._PHI = np.array([]) self._P = np.array([]) + # Scaling for better condition number + self._sx = np.array([]) self._scale = np.array([]) self._avg = np.array([]) self._change_scale_factor = 2.0 # Change the scale factor when new scale is 2 times larger than the current one @@ -210,11 +212,15 @@ def reserve(self, maxeval: int, dim: int) -> None: if self._x.size == 0: self._x = np.empty((maxeval, dim)) + self._sx = np.empty((maxeval, dim)) else: additional_rows = max(0, maxeval - self._x.shape[0]) self._x = np.concatenate( (self._x, np.empty((additional_rows, dim))), axis=0 ) + self._sx = np.concatenate( + (self._sx, np.empty((additional_rows, dim))), axis=0 + ) if self._fx.size == 0: self._fx = np.empty(maxeval) @@ -375,7 +381,7 @@ def __call__(self, x: np.ndarray) -> tuple[np.ndarray, np.ndarray]: # Scale x and samples xscaled = (x.reshape(-1, dim) - self._avg) / self._scale - sscaled = (self.samples() - self._avg) / self._scale + sscaled = self._sx[0 : self._m, :] # compute pairwise distances between candidates and sampled points D = cdist(xscaled, sscaled) * self._eps @@ -415,7 +421,7 @@ def jac(self, x: np.ndarray) -> np.ndarray: # Scale x and samples xscaled = (x.reshape(-1, dim) - self._avg) / self._scale - sscaled = (self.samples() - self._avg) / self._scale + sscaled = self._sx[0 : self._m, :] # compute pairwise distances between candidates and sampled points d = cdist(xscaled, sscaled).flatten() @@ -502,13 +508,16 @@ def update_samples(self, xNew: np.ndarray, distNew=None) -> None: if newm == 0: return + # Update x + self._x[oldm:m, :] = xNew + # Compute new scaling factor if len(self._scale) > 0: xmax = np.max( - np.concatenate((xNew, self.samples()), axis=0), axis=0 + np.concatenate((xNew, self._x[0:oldm, :]), axis=0), axis=0 ) xmin = np.min( - np.concatenate((xNew, self.samples()), axis=0), axis=0 + np.concatenate((xNew, self._x[0:oldm, :]), axis=0), axis=0 ) new_scale = (xmax - xmin) / 2 new_scale = np.where(new_scale == 0, 1, new_scale) @@ -524,14 +533,15 @@ def update_samples(self, xNew: np.ndarray, distNew=None) -> None: new_scale < self._scale * self._change_scale_factor ): # Scale points - xscaled = (xNew - self._avg) / self._scale + xscaled = self._sx[oldm:m, :] + xscaled[:] = (xNew - self._avg) / self._scale # Compute distances between new points and sampled points if distNew is None: if oldm == 0: distNew = cdist(xscaled, xscaled) else: - sscaled = (self.samples() - self._avg) / self._scale + sscaled = (self._x[0:oldm, :] - self._avg) / self._scale distNew = cdist( xscaled, np.concatenate((sscaled, xscaled), axis=0), @@ -549,8 +559,8 @@ def update_samples(self, xNew: np.ndarray, distNew=None) -> None: self._avg = (xmax + xmin) / 2 # Scale points - xscaled = np.concatenate((self.samples(), xNew), axis=0) - xscaled = (xscaled - self._avg) / self._scale + xscaled = self._sx[0:m, :] + xscaled[:] = (self._x[0:m, :] - self._avg) / self._scale # Recompute distances between sampled points distNew = cdist(xscaled, xscaled) @@ -559,9 +569,6 @@ def update_samples(self, xNew: np.ndarray, distNew=None) -> None: self._PHI[0:m, 0:m] = phi(distNew * self._eps) self._P[0:m, :] = self.pbasis(xscaled) - # Update x - self._x[oldm:m, :] = xNew - # Update m self._m = m @@ -619,13 +626,13 @@ def create_initial_design( self._avg = (xmax + xmin) / 2 # Compute distances between new points and sampled points - xscaled = (self.samples() - self._avg) / self._scale - distNew = cdist(xscaled, xscaled) + self._sx[0:m, :] = (self.samples() - self._avg) / self._scale + distNew = cdist(self._sx[0:m, :], self._sx[0:m, :]) # Set matrices _PHI and _P phi = KERNEL_FUNC[self._kernel] self._PHI[0:m, 0:m] = phi(distNew * self._eps) - self._P[0:m, :] = self.pbasis(xscaled) + self._P[0:m, :] = self.pbasis(self._sx[0:m, :]) # Coefficients are not valid self._valid_coefficients = False @@ -749,7 +756,7 @@ def mu_measure(self, x: np.ndarray, xdist=None, LDLt=()) -> float: # compute rbf value of the new point x xscaled = (x - self._avg) / self._scale - sscaled = (self.samples() - self._avg) / self._scale + sscaled = self._sx[0 : self._m, :] if xdist is None: xdist = cdist(xscaled.reshape(1, -1), sscaled) newRow = np.concatenate( From 40b933dba645e2267b7e28e94c981bdd1e52b95f Mon Sep 17 00:00:00 2001 From: Weslley da Silva Pereira Date: Mon, 19 Aug 2024 13:57:22 -0600 Subject: [PATCH 24/24] Update to v0.4.2 --- README.md | 26 ++++++++++++++++++- blackboxopt/__init__.py | 2 +- blackboxopt/acquisition.py | 2 +- blackboxopt/optimize.py | 8 +++--- blackboxopt/problem.py | 2 +- blackboxopt/rbf.py | 2 +- blackboxopt/sampling.py | 2 +- docs/conf.py | 2 +- examples/multiobj/pareto_front.ipynb | 2 +- examples/multiobj/socemo.ipynb | 2 +- examples/opt_with_constr/example_gosac_1.py | 2 +- examples/opt_with_constr/example_gosac_2.py | 2 +- examples/sampling.ipynb | 2 +- examples/single_obj_rbf/LocalStochRBFstop.py | 2 +- .../compareLearningStrategies.py | 2 +- examples/single_obj_rbf/data.py | 2 +- examples/single_obj_rbf/datainput_Branin.py | 2 +- .../datainput_BraninWithInteger.py | 2 +- examples/single_obj_rbf/datainput_hartman3.py | 2 +- .../single_obj_rbf/datainput_rastrigin.py | 2 +- examples/single_obj_rbf/optprogram1.py | 2 +- examples/vlse_benchmark/vlse_bench.ipynb | 2 +- examples/vlse_benchmark/vlse_bench.py | 2 +- pyproject.toml | 2 +- tests/test_optimize.py | 2 +- tests/test_rbf.py | 2 +- tests/test_sampling.py | 2 +- tests/test_vlse_bench.py | 2 +- tests/vlse_benchmark/__init__.py | 2 +- 29 files changed, 56 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index 2ad941c0..a64c3a77 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,31 @@ Surrogate models and active learning for scientific applications. ## Building -This project uses [pdm](https://pdm-project.org/en/stable/) as its package manager. With pdm installed, run `pdm install` at the root of this repository to install the dependencies. The file [pyproject.toml](pyproject.toml) has the list of dependencies and configurations for the project. Use `pdm build` to build the project. The build artifacts will be in the `dist` directory. Please, find more information about pdm in its website. +### Binaries + +The binaries for the latest version are available at https://github.com/NREL/bbopt/releases/latest. They can be installed through standard installation, e.g., + +using pip (https://pip.pypa.io/en/stable/cli/pip_install/): + +```sh +python -m pip install +https://github.com/NREL/bbopt/archive/refs/tags/v0.4.2.tar.gz +``` + +using conda (https://docs.anaconda.com/working-with-conda/packages/install-packages/): + +```sh +conda install +https://github.com/NREL/bbopt/archive/refs/tags/v0.4.2.tar.gz +``` + +### From source + +This package contains a [pyproject.toml](pyproject.toml) with the list of requirements and dependencies (More about `pyproject.toml` at https://packaging.python.org/en/latest/specifications/pyproject-toml/). This project is configured to use the package manager [pdm](https://pdm-project.org/en/stable/). With pdm installed, run `pdm install` at the root of this repository to install the dependencies. The file [pyproject.toml](pyproject.toml) has the list of dependencies and configurations for the project. Use `pdm build` to build the packages binaries in the `dist` directory. Then follow the steps in the [Binaries section](#binaries) to install. + +### For developers + +Install the package manager [pdm](https://pdm-project.org/en/stable/). To install all the dependencies listted in the [pyproject.toml](pyproject.toml), run `pdm install`. ## Documentation diff --git a/blackboxopt/__init__.py b/blackboxopt/__init__.py index 7c2e8fbc..3ca576d8 100644 --- a/blackboxopt/__init__.py +++ b/blackboxopt/__init__.py @@ -16,7 +16,7 @@ # along with this program. If not, see . __all__ = ["acquisition", "optimize", "sampling", "rbf"] -__version__ = "0.4.1" +__version__ = "0.4.2" from . import acquisition from . import optimize diff --git a/blackboxopt/acquisition.py b/blackboxopt/acquisition.py index 86f2b1f2..342f200e 100644 --- a/blackboxopt/acquisition.py +++ b/blackboxopt/acquisition.py @@ -31,7 +31,7 @@ "Haoyu Jia", "Weslley S. Pereira", ] -__version__ = "0.4.1" +__version__ = "0.4.2" __deprecated__ = False import numpy as np diff --git a/blackboxopt/optimize.py b/blackboxopt/optimize.py index efef7ffc..b71aff0a 100644 --- a/blackboxopt/optimize.py +++ b/blackboxopt/optimize.py @@ -31,7 +31,7 @@ "Haoyu Jia", "Weslley S. Pereira", ] -__version__ = "0.4.1" +__version__ = "0.4.2" __deprecated__ = False from typing import Callable, Optional, Union @@ -781,9 +781,9 @@ def multistart_stochastic_response_surface( if out_local.fx < out.fx: out.x[:] = out_local.x out.fx = out_local.fx - out.samples[ - out.nfev : out.nfev + out_local.nfev, : - ] = out_local.samples + out.samples[out.nfev : out.nfev + out_local.nfev, :] = ( + out_local.samples + ) out.fsamples[out.nfev : out.nfev + out_local.nfev] = out_local.fsamples out.nfev = out.nfev + out_local.nfev diff --git a/blackboxopt/problem.py b/blackboxopt/problem.py index a8d51dcf..ad2d4f5d 100644 --- a/blackboxopt/problem.py +++ b/blackboxopt/problem.py @@ -20,7 +20,7 @@ __maintainer__ = "Weslley S. Pereira" __email__ = "weslley.dasilvapereira@nrel.gov" __credits__ = ["Weslley S. Pereira"] -__version__ = "0.4.1" +__version__ = "0.4.2" __deprecated__ = False import numpy as np diff --git a/blackboxopt/rbf.py b/blackboxopt/rbf.py index 28fb0626..9057145a 100644 --- a/blackboxopt/rbf.py +++ b/blackboxopt/rbf.py @@ -20,7 +20,7 @@ __maintainer__ = "Weslley S. Pereira" __email__ = "weslley.dasilvapereira@nrel.gov" __credits__ = ["Weslley S. Pereira"] -__version__ = "0.4.1" +__version__ = "0.4.2" __deprecated__ = False from typing import Optional diff --git a/blackboxopt/sampling.py b/blackboxopt/sampling.py index a99620b9..5ce3b102 100644 --- a/blackboxopt/sampling.py +++ b/blackboxopt/sampling.py @@ -31,7 +31,7 @@ "Haoyu Jia", "Weslley S. Pereira", ] -__version__ = "0.4.1" +__version__ = "0.4.2" __deprecated__ = False import numpy as np diff --git a/docs/conf.py b/docs/conf.py index 01b8b128..14f77fa2 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -17,7 +17,7 @@ project = "Black-box Opt" copyright = "2024, Alliance for Sustainable Energy, LLC" author = "Weslley S. Pereira" -release = "0.4.1" +release = "0.4.2" # -- General configuration --------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration diff --git a/examples/multiobj/pareto_front.ipynb b/examples/multiobj/pareto_front.ipynb index 56159921..42b0e873 100644 --- a/examples/multiobj/pareto_front.ipynb +++ b/examples/multiobj/pareto_front.ipynb @@ -29,7 +29,7 @@ "__maintainer__ = \"Weslley S. Pereira\"\n", "__email__ = \"weslley.dasilvapereira@nrel.gov\"\n", "__credits__ = [\"Weslley S. Pereira\"]\n", - "__version__ = \"0.4.1\"\n", + "__version__ = \"0.4.2\"\n", "__deprecated__ = False" ] }, diff --git a/examples/multiobj/socemo.ipynb b/examples/multiobj/socemo.ipynb index fef9d4e5..be5ffbc0 100644 --- a/examples/multiobj/socemo.ipynb +++ b/examples/multiobj/socemo.ipynb @@ -28,7 +28,7 @@ "__maintainer__ = \"Weslley S. Pereira\"\n", "__email__ = \"weslley.dasilvapereira@nrel.gov\"\n", "__credits__ = [\"Weslley S. Pereira\"]\n", - "__version__ = \"0.4.1\"\n", + "__version__ = \"0.4.2\"\n", "__deprecated__ = False" ] }, diff --git a/examples/opt_with_constr/example_gosac_1.py b/examples/opt_with_constr/example_gosac_1.py index 557f3875..b5d6e5bf 100644 --- a/examples/opt_with_constr/example_gosac_1.py +++ b/examples/opt_with_constr/example_gosac_1.py @@ -20,7 +20,7 @@ __maintainer__ = "Weslley S. Pereira" __email__ = "weslley.dasilvapereira@nrel.gov" __credits__ = ["Juliane Mueller", "Weslley S. Pereira"] -__version__ = "0.4.1" +__version__ = "0.4.2" __deprecated__ = False from blackboxopt.optimize import gosac diff --git a/examples/opt_with_constr/example_gosac_2.py b/examples/opt_with_constr/example_gosac_2.py index 34f32e8f..e9ff34f7 100644 --- a/examples/opt_with_constr/example_gosac_2.py +++ b/examples/opt_with_constr/example_gosac_2.py @@ -20,7 +20,7 @@ __maintainer__ = "Weslley S. Pereira" __email__ = "weslley.dasilvapereira@nrel.gov" __credits__ = ["Juliane Mueller", "Weslley S. Pereira"] -__version__ = "0.4.1" +__version__ = "0.4.2" __deprecated__ = False from blackboxopt.optimize import gosac diff --git a/examples/sampling.ipynb b/examples/sampling.ipynb index 413766af..1a857fd2 100644 --- a/examples/sampling.ipynb +++ b/examples/sampling.ipynb @@ -28,7 +28,7 @@ "__maintainer__ = \"Weslley S. Pereira\"\n", "__email__ = \"weslley.dasilvapereira@nrel.gov\"\n", "__credits__ = [\"Weslley S. Pereira\"]\n", - "__version__ = \"0.4.1\"\n", + "__version__ = \"0.4.2\"\n", "__deprecated__ = False" ] }, diff --git a/examples/single_obj_rbf/LocalStochRBFstop.py b/examples/single_obj_rbf/LocalStochRBFstop.py index 75e6dde1..2628ded4 100644 --- a/examples/single_obj_rbf/LocalStochRBFstop.py +++ b/examples/single_obj_rbf/LocalStochRBFstop.py @@ -26,7 +26,7 @@ "Haoyu Jia", "Weslley S. Pereira", ] -__version__ = "0.4.1" +__version__ = "0.4.2" __deprecated__ = False from optprogram1 import read_check_data_file diff --git a/examples/single_obj_rbf/compareLearningStrategies.py b/examples/single_obj_rbf/compareLearningStrategies.py index 3fb6daec..c526828f 100644 --- a/examples/single_obj_rbf/compareLearningStrategies.py +++ b/examples/single_obj_rbf/compareLearningStrategies.py @@ -20,7 +20,7 @@ __maintainer__ = "Weslley S. Pereira" __email__ = "weslley.dasilvapereira@nrel.gov" __credits__ = ["Weslley S. Pereira"] -__version__ = "0.4.1" +__version__ = "0.4.2" __deprecated__ = False diff --git a/examples/single_obj_rbf/data.py b/examples/single_obj_rbf/data.py index 5183a485..4c0b0c58 100644 --- a/examples/single_obj_rbf/data.py +++ b/examples/single_obj_rbf/data.py @@ -26,7 +26,7 @@ "Haoyu Jia", "Weslley S. Pereira", ] -__version__ = "0.4.1" +__version__ = "0.4.2" __deprecated__ = False from dataclasses import dataclass diff --git a/examples/single_obj_rbf/datainput_Branin.py b/examples/single_obj_rbf/datainput_Branin.py index 56f46ba9..2bf5cd56 100644 --- a/examples/single_obj_rbf/datainput_Branin.py +++ b/examples/single_obj_rbf/datainput_Branin.py @@ -26,7 +26,7 @@ "Haoyu Jia", "Weslley S. Pereira", ] -__version__ = "0.4.1" +__version__ = "0.4.2" __deprecated__ = False import numpy as np diff --git a/examples/single_obj_rbf/datainput_BraninWithInteger.py b/examples/single_obj_rbf/datainput_BraninWithInteger.py index 056f2cf1..7a2d526c 100644 --- a/examples/single_obj_rbf/datainput_BraninWithInteger.py +++ b/examples/single_obj_rbf/datainput_BraninWithInteger.py @@ -26,7 +26,7 @@ "Haoyu Jia", "Weslley S. Pereira", ] -__version__ = "0.4.1" +__version__ = "0.4.2" __deprecated__ = False import numpy as np diff --git a/examples/single_obj_rbf/datainput_hartman3.py b/examples/single_obj_rbf/datainput_hartman3.py index da39411a..9067c1d7 100644 --- a/examples/single_obj_rbf/datainput_hartman3.py +++ b/examples/single_obj_rbf/datainput_hartman3.py @@ -26,7 +26,7 @@ "Haoyu Jia", "Weslley S. Pereira", ] -__version__ = "0.4.1" +__version__ = "0.4.2" __deprecated__ = False import numpy as np diff --git a/examples/single_obj_rbf/datainput_rastrigin.py b/examples/single_obj_rbf/datainput_rastrigin.py index 36ceeae7..2264c336 100644 --- a/examples/single_obj_rbf/datainput_rastrigin.py +++ b/examples/single_obj_rbf/datainput_rastrigin.py @@ -26,7 +26,7 @@ "Haoyu Jia", "Weslley S. Pereira", ] -__version__ = "0.4.1" +__version__ = "0.4.2" __deprecated__ = False import numpy as np diff --git a/examples/single_obj_rbf/optprogram1.py b/examples/single_obj_rbf/optprogram1.py index a4eb54ff..6f406538 100644 --- a/examples/single_obj_rbf/optprogram1.py +++ b/examples/single_obj_rbf/optprogram1.py @@ -31,7 +31,7 @@ "Haoyu Jia", "Weslley S. Pereira", ] -__version__ = "0.4.1" +__version__ = "0.4.2" __deprecated__ = False diff --git a/examples/vlse_benchmark/vlse_bench.ipynb b/examples/vlse_benchmark/vlse_bench.ipynb index d4e57b75..23f35fe3 100644 --- a/examples/vlse_benchmark/vlse_bench.ipynb +++ b/examples/vlse_benchmark/vlse_bench.ipynb @@ -28,7 +28,7 @@ "__maintainer__ = \"Weslley S. Pereira\"\n", "__email__ = \"weslley.dasilvapereira@nrel.gov\"\n", "__credits__ = [\"Weslley S. Pereira\"]\n", - "__version__ = \"0.4.1\"\n", + "__version__ = \"0.4.2\"\n", "__deprecated__ = False" ] }, diff --git a/examples/vlse_benchmark/vlse_bench.py b/examples/vlse_benchmark/vlse_bench.py index 3aef93ef..7357643b 100644 --- a/examples/vlse_benchmark/vlse_bench.py +++ b/examples/vlse_benchmark/vlse_bench.py @@ -20,7 +20,7 @@ __maintainer__ = "Weslley S. Pereira" __email__ = "weslley.dasilvapereira@nrel.gov" __credits__ = ["Weslley S. Pereira"] -__version__ = "0.4.1" +__version__ = "0.4.2" __deprecated__ = False import os diff --git a/pyproject.toml b/pyproject.toml index ff407e5b..f3c37275 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "blackboxopt" -version = "0.4.1" +version = "0.4.2" description = "Surrogate models and active learning for scientific applications" authors = [ {name = "Weslley da Silva Pereira", email = "weslley.dasilvapereira@nrel.gov"}, diff --git a/tests/test_optimize.py b/tests/test_optimize.py index 8be4242d..e482c7cc 100644 --- a/tests/test_optimize.py +++ b/tests/test_optimize.py @@ -20,7 +20,7 @@ __maintainer__ = "Weslley S. Pereira" __email__ = "weslley.dasilvapereira@nrel.gov" __credits__ = ["Weslley S. Pereira"] -__version__ = "0.4.1" +__version__ = "0.4.2" __deprecated__ = False import numpy as np diff --git a/tests/test_rbf.py b/tests/test_rbf.py index c4adbd93..11312fd6 100644 --- a/tests/test_rbf.py +++ b/tests/test_rbf.py @@ -20,7 +20,7 @@ __maintainer__ = "Weslley S. Pereira" __email__ = "weslley.dasilvapereira@nrel.gov" __credits__ = ["Weslley S. Pereira"] -__version__ = "0.4.1" +__version__ = "0.4.2" __deprecated__ = False import numpy as np diff --git a/tests/test_sampling.py b/tests/test_sampling.py index 221ae184..5068c5d5 100644 --- a/tests/test_sampling.py +++ b/tests/test_sampling.py @@ -20,7 +20,7 @@ __maintainer__ = "Weslley S. Pereira" __email__ = "weslley.dasilvapereira@nrel.gov" __credits__ = ["Weslley S. Pereira"] -__version__ = "0.4.1" +__version__ = "0.4.2" __deprecated__ = False import numpy as np diff --git a/tests/test_vlse_bench.py b/tests/test_vlse_bench.py index e6c438ea..28064162 100644 --- a/tests/test_vlse_bench.py +++ b/tests/test_vlse_bench.py @@ -20,7 +20,7 @@ __maintainer__ = "Weslley S. Pereira" __email__ = "weslley.dasilvapereira@nrel.gov" __credits__ = ["Weslley S. Pereira"] -__version__ = "0.4.1" +__version__ = "0.4.2" __deprecated__ = False from copy import deepcopy diff --git a/tests/vlse_benchmark/__init__.py b/tests/vlse_benchmark/__init__.py index 13ad92f2..129511d6 100644 --- a/tests/vlse_benchmark/__init__.py +++ b/tests/vlse_benchmark/__init__.py @@ -27,7 +27,7 @@ __maintainer__ = "Weslley S. Pereira" __email__ = "weslley.dasilvapereira@nrel.gov" __credits__ = ["Sonja Surjanovic", "Derek Bingham", "Weslley S. Pereira"] -__version__ = "0.4.1" +__version__ = "0.4.2" __deprecated__ = False from rpy2.robjects import r