surrogates_interface 4.0.2__tar.gz → 4.0.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: surrogates_interface
3
- Version: 4.0.2
3
+ Version: 4.0.3
4
4
  Summary: Interface for surrogate models.
5
5
  Home-page: https://gitlab.windenergy.dtu.dk/surrogate-models/surrogate-models-interface
6
6
  License: MIT
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "surrogates_interface"
3
- version = "4.0.2"
3
+ version = "4.0.3"
4
4
  description = "Interface for surrogate models."
5
5
  authors = ["DTU Wind and Energy Systems"]
6
6
  maintainers = [
@@ -1,44 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- import numpy as np
3
- import numpy.testing as npt
4
- import pytest
5
-
6
- from surrogates_interface.domains import BoxDomain, GenericDomain
7
-
8
-
9
- class TestBoxDomain:
10
- @staticmethod
11
- def test_in_domain():
12
- min = np.array([-1.0, +2.0, -15.0])
13
- max = np.array([+1.0, +7.0, +8.0])
14
- x = np.array(
15
- [[0.0, 0.0, 0.0], [0.0, 4.0, 9.0], [0.0, 4.0, 0.0], [3.0, 4.0, 6.0]]
16
- )
17
- box = BoxDomain(min, max)
18
- out = box.in_domain(x)
19
- npt.assert_array_equal(out, np.array([False, False, True, False]))
20
-
21
- @staticmethod
22
- def test_bad_box():
23
- min = np.array([-1.0, +7.0])
24
- max = np.array([+1.0, -15.0])
25
- with pytest.raises(AssertionError):
26
- BoxDomain(min, max)
27
-
28
- @staticmethod
29
- def test_eq():
30
- box1 = BoxDomain([-1.0, +2.0, -15.0], [+1.0, +7.0, +8.0])
31
- box2 = BoxDomain([-1.0, -5.0, -15.0], [+1.0, +7.0, +8.0])
32
- assert not box1 == box2
33
-
34
- @staticmethod
35
- def test_eq_different_type():
36
- class DummyDomain(GenericDomain):
37
- fields = []
38
-
39
- def in_domain():
40
- pass
41
-
42
- box1 = BoxDomain([-1.0, +2.0, -15.0], [+1.0, +7.0, +8.0])
43
- box2 = DummyDomain()
44
- assert not box1 == box2
@@ -1,12 +0,0 @@
1
- try:
2
- import tomllib # From Python 3.11.
3
- except ModuleNotFoundError:
4
- import tomli as tomllib # Before Python 3.11.
5
-
6
- import surrogates_interface
7
-
8
-
9
- def test_version():
10
- with open("pyproject.toml", "rb") as fid:
11
- data = tomllib.load(fid)
12
- assert surrogates_interface.__version__ == data["tool"]["poetry"]["version"]
@@ -1,137 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- import numpy as np
4
- import numpy.testing as npt
5
- import openmdao.api as om
6
- import pytest
7
- from sklearn.decomposition import PCA
8
- from sklearn.preprocessing import MinMaxScaler, PowerTransformer
9
-
10
- from surrogates_interface.openmdao import InputOutputType, SurrogateModelComp
11
- from surrogates_interface.surrogates import SurrogateModel
12
- from surrogates_interface.transformers import Transformer
13
-
14
-
15
- class Paraboloid(SurrogateModel):
16
- """Define a paraboloid."""
17
-
18
- coef_1 = np.array([0.2, 0.5, 0.3])
19
- coef_2 = np.array([1.2, 1.5, 1.3])
20
-
21
- def _predict_model_output(self, x):
22
- y = np.column_stack(
23
- (np.sum(self.coef_1 * x**2, axis=1), np.sum(self.coef_2 * x**2, axis=1))
24
- )
25
- return y
26
-
27
- def _predict_model_jacobian(self, x):
28
- y = self._predict_model_output(x)
29
- jac = np.stack((2.0 * self.coef_1 * x, 2.0 * self.coef_2 * x), axis=1)
30
- return y, jac
31
-
32
-
33
- @pytest.fixture
34
- def make_data():
35
- rng = np.random.default_rng(seed=123)
36
- n_points = 100
37
- n_inputs_original = 5
38
- n_outputs_original = 4
39
- input = rng.uniform(-1.0, +1.0, size=(n_points, n_inputs_original))
40
- # Introduce linear correlation between some input features.
41
- input[:, 1] = 2.0 * input[:, 0]
42
- input[:, 2] = 3.0 * input[:, 0] - 5.0
43
- # Build input transformers.
44
- sklearn_input_transformers = [
45
- PowerTransformer(standardize=False),
46
- PCA(n_components=3, whiten=False),
47
- ]
48
- input_transformed = input.copy()
49
- for transformer in sklearn_input_transformers:
50
- input_transformed = transformer.fit_transform(input_transformed)
51
- si_input_transformers = [
52
- Transformer.from_sklearn(t) for t in sklearn_input_transformers
53
- ]
54
- # Make a dummy output. We only need it to create the transformers.
55
- output = np.zeros((n_points, n_outputs_original))
56
- output[:, 0] = np.sin(input[:, 0]) * np.cos(input[:, 4])
57
- output[:, 1] = np.sum(input**2, axis=1)
58
- # Introduce linear correlation between some output features.
59
- output[:, 2] = 1.1 * output[:, 0]
60
- output[:, 3] = 0.5 * output[:, 1]
61
- # Build output transformers.
62
- sklearn_output_transformers = [
63
- MinMaxScaler(feature_range=(-1.0, +1.0), clip=False),
64
- PCA(n_components=2, whiten=False),
65
- ]
66
- output_transformed = output.copy()
67
- for transformer in sklearn_output_transformers:
68
- output_transformed = transformer.fit_transform(output_transformed)
69
- si_output_transformers = [
70
- Transformer.from_sklearn(t) for t in sklearn_output_transformers
71
- ]
72
- # Build the surrogate model.
73
- si_model = Paraboloid(
74
- [], # model is dummy.
75
- input_transformers=si_input_transformers,
76
- output_transformers=si_output_transformers,
77
- n_inputs=n_inputs_original,
78
- n_outputs=n_outputs_original,
79
- )
80
- # Evaluate it on the input, and overwrite the transformed output.
81
- output_transformed = si_model._predict_model_output(input_transformed)
82
- # Apply inverse output transformations and overwrite the original output.
83
- output = output_transformed.copy()
84
- for transformer in reversed(si_output_transformers):
85
- output = transformer.inverse_transform(output, inplace=False)
86
- return (
87
- si_model,
88
- input,
89
- output,
90
- )
91
-
92
-
93
- def test_jacobian(make_data):
94
- si_model, input, _ = make_data
95
- # Compute exact Jacobian.
96
- jacobian_si = si_model.predict_jacobian(input)
97
- # Compute Jacobian using central finite differences.
98
- jacobian_fd = np.zeros_like(jacobian_si)
99
- h = 1e-6
100
- for i in range(input.shape[1]):
101
- xm = input.copy()
102
- xp = input.copy()
103
- xm[:, i] -= h
104
- xp[:, i] += h
105
- jacobian_fd[:, :, i] = si_model.predict_output(xp) - si_model.predict_output(xm)
106
- jacobian_fd /= 2.0 * h
107
- # Test.
108
- npt.assert_allclose(jacobian_si, jacobian_fd, rtol=2e-7)
109
-
110
-
111
- def test_om_compute_partials_joined_joined(make_data):
112
- # Get the data.
113
- si_model, input, _ = make_data
114
- # Make the OpenMDAO problem.
115
- problem = om.Problem()
116
- component = SurrogateModelComp(
117
- model=si_model,
118
- input_type=InputOutputType.JOINED,
119
- output_type=InputOutputType.JOINED,
120
- n_points=input.shape[0],
121
- )
122
- problem.model.add_subsystem(
123
- "surrogate", component, promotes_inputs=["x"], promotes_outputs=["y"]
124
- )
125
- problem.setup()
126
- # Set the input.
127
- problem.set_val("x", input)
128
- # Check partial derivatives.
129
- om_partials = problem.check_partials(
130
- out_stream=None, step=1e-6, step_calc="abs", form="central"
131
- )
132
- # Jacobian computed by finite differences.
133
- jacobian_fd = om_partials["surrogate"][("y", "x")]["J_fd"]
134
- # Exact Jacobian.
135
- jacobian_exact = om_partials["surrogate"][("y", "x")]["J_fwd"]
136
- # Test.
137
- npt.assert_allclose(jacobian_fd, jacobian_exact, rtol=2e-7)
@@ -1,258 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- import uuid
4
-
5
- import numpy as np
6
- import numpy.testing as npt
7
- import pytest
8
- from smt.surrogate_models import KRG, RBF
9
-
10
- from surrogates_interface.domains import BoxDomain
11
- from surrogates_interface.surrogates import SMTModel
12
-
13
- # %% Test SMTModel.
14
-
15
-
16
- @pytest.fixture
17
- def make_data_siso_rbf():
18
- # Example from https://smt.readthedocs.io/en/stable/_src_docs/surrogate_models/rbf.html
19
- xt = np.array([0.0, 1.0, 2.0, 3.0, 4.0]).reshape(-1, 1)
20
- yt = np.array([0.0, 1.0, 1.5, 0.9, 1.0]).reshape(-1, 1)
21
-
22
- sm = RBF(d0=5, print_global=False)
23
-
24
- sm.set_training_values(xt, yt)
25
- sm.train()
26
-
27
- x = np.linspace(0.0, 4.0, 100).reshape(-1, 1)
28
- y = sm.predict_values(x)
29
-
30
- model = SMTModel(
31
- sm,
32
- n_inputs=1,
33
- n_outputs=1,
34
- )
35
- return model, x, y
36
-
37
-
38
- @pytest.fixture
39
- def make_data_siso_krg():
40
- # Example from https://smt.readthedocs.io/en/stable/_src_docs/surrogate_models/rbf.html
41
- xt = np.array([0.0, 1.0, 2.0, 3.0, 4.0]).reshape(-1, 1)
42
- yt = np.array([0.0, 1.0, 1.5, 0.9, 1.0]).reshape(-1, 1)
43
-
44
- sm = KRG(print_global=False)
45
-
46
- sm.set_training_values(xt, yt)
47
- sm.train()
48
-
49
- x = np.linspace(0.0, 4.0, 100).reshape(-1, 1)
50
- y = sm.predict_values(x)
51
-
52
- model = SMTModel(
53
- sm,
54
- n_inputs=1,
55
- n_outputs=1,
56
- )
57
- return model, x, y
58
-
59
-
60
- def test_predict_output_siso_rbf(make_data_siso_rbf):
61
- si_model, input, output = make_data_siso_rbf
62
- output_si = si_model.predict_output(input)
63
- npt.assert_array_equal(output_si, output)
64
-
65
-
66
- def test_predict_jacobian_siso_rbf(make_data_siso_rbf):
67
- si_model, input, _ = make_data_siso_rbf
68
- # Compute jacobian using the chain rule and SMT.
69
- jacobian_si = si_model.predict_jacobian(input)
70
- # Compute jacobian using central finite differences.
71
- h = 1e-5
72
- jacobian_fd = np.zeros(jacobian_si.shape)
73
- jacobian_fd[:, 0, 0] = (
74
- si_model.predict_output(input + h).ravel()
75
- - si_model.predict_output(input - h).ravel()
76
- ) / (2.0 * h)
77
- npt.assert_allclose(jacobian_si, jacobian_fd, rtol=2e-5, atol=5e-7)
78
-
79
-
80
- @pytest.fixture
81
- def make_data_miso_rbf():
82
- # Build input and output.
83
- domain = BoxDomain([-5.0, -10.0], [10.0, 2.0])
84
- xt = np.column_stack(
85
- (
86
- np.linspace(domain.min[0], domain.max[0], 11),
87
- np.linspace(domain.min[1], domain.max[1], 11),
88
- )
89
- )
90
- yt = np.sum(xt**2, axis=1, keepdims=True)
91
-
92
- # Train.
93
- sm = RBF(d0=5, print_global=False)
94
-
95
- sm.set_training_values(xt, yt)
96
- sm.train()
97
-
98
- x = np.column_stack(
99
- (
100
- np.linspace(domain.min[0], domain.max[0], 21),
101
- np.linspace(domain.min[1], domain.max[1], 21),
102
- )
103
- )
104
- y = sm.predict_values(x)
105
-
106
- model = SMTModel(
107
- sm,
108
- n_inputs=2,
109
- n_outputs=1,
110
- domain=domain,
111
- )
112
- return model, x, y
113
-
114
-
115
- def test_predict_output_miso_rbf(make_data_miso_rbf):
116
- si_model, input, output = make_data_miso_rbf
117
- output_si = si_model.predict_output(input)
118
- npt.assert_array_equal(output_si, output)
119
-
120
-
121
- def test_predict_jacobian_miso_rbf(make_data_miso_rbf):
122
- si_model, input, _ = make_data_miso_rbf
123
- # Compute jacobian using the chain rule and SMT.
124
- jacobian_si = si_model.predict_jacobian(input)
125
- # Compute jacobian using central finite differences.
126
- jacobian_fd = np.zeros(jacobian_si.shape)
127
- h = 1e-5
128
- for i in range(input.shape[1]):
129
- xm = input.copy()
130
- xp = input.copy()
131
- xm[:, i] -= h
132
- xp[:, i] += h
133
- jacobian_fd[:, 0, i] = (
134
- si_model.predict_output(xp).ravel() - si_model.predict_output(xm).ravel()
135
- )
136
- jacobian_fd /= 2.0 * h
137
- npt.assert_allclose(jacobian_si, jacobian_fd, rtol=5e-7)
138
-
139
-
140
- @pytest.fixture
141
- def make_data_simo_rbf():
142
- # Build input and output.
143
- domain = BoxDomain([-5.0], [10.0])
144
- xt = np.linspace(domain.min[0], domain.max[0], 11).reshape(-1, 1)
145
- yt = np.column_stack((xt**2, 0.5 * xt**2))
146
-
147
- # Train.
148
- sm = RBF(d0=5, print_global=False)
149
-
150
- sm.set_training_values(xt, yt)
151
- sm.train()
152
-
153
- x = np.linspace(domain.min[0], domain.max[0], 21).reshape(-1, 1)
154
- y = sm.predict_values(x)
155
-
156
- model = SMTModel(
157
- sm,
158
- n_inputs=1,
159
- n_outputs=2,
160
- domain=domain,
161
- )
162
- return model, x, y
163
-
164
-
165
- def test_predict_output_simo_rbf(make_data_simo_rbf):
166
- si_model, input, output = make_data_simo_rbf
167
- output_si = si_model.predict_output(input)
168
- npt.assert_array_equal(output_si, output)
169
-
170
-
171
- def test_predict_jacobian_simo_rbf(make_data_simo_rbf):
172
- si_model, input, _ = make_data_simo_rbf
173
- # Compute jacobian using the chain rule and SMT.
174
- jacobian_si = si_model.predict_jacobian(input)
175
- # Compute jacobian using central finite differences.
176
- h = 1e-5
177
- jacobian_fd = np.zeros(jacobian_si.shape)
178
- jacobian_fd[:, :, 0] = (
179
- si_model.predict_output(input + h) - si_model.predict_output(input - h)
180
- ) / (2.0 * h)
181
- npt.assert_allclose(jacobian_si, jacobian_fd, rtol=5e-7)
182
-
183
-
184
- @pytest.fixture
185
- def make_data_mimo_rbf():
186
- # Build input and output.
187
- domain = BoxDomain([-5.0, -10.0], [10.0, 2.0])
188
- xt = np.column_stack(
189
- (
190
- np.linspace(domain.min[0], domain.max[0], 11),
191
- np.linspace(domain.min[1], domain.max[1], 11),
192
- )
193
- )
194
- yt = np.column_stack(
195
- (0.8 * xt[:, 0] ** 2, 0.5 * xt[:, 1] ** 2, np.sum(xt**2, axis=1))
196
- )
197
-
198
- # Train.
199
- sm = RBF(d0=5, print_global=False)
200
-
201
- sm.set_training_values(xt, yt)
202
- sm.train()
203
-
204
- x = np.column_stack(
205
- (
206
- np.linspace(domain.min[0], domain.max[0], 21),
207
- np.linspace(domain.min[1], domain.max[1], 21),
208
- )
209
- )
210
- y = sm.predict_values(x)
211
-
212
- model = SMTModel(
213
- sm,
214
- n_inputs=2,
215
- n_outputs=3,
216
- domain=domain,
217
- )
218
- return model, x, y
219
-
220
-
221
- def test_predict_output_mimo_rbf(make_data_mimo_rbf):
222
- si_model, input, output = make_data_mimo_rbf
223
- output_si = si_model.predict_output(input)
224
- npt.assert_array_equal(output_si, output)
225
-
226
-
227
- def test_predict_jacobian_mimo_rbf(make_data_mimo_rbf):
228
- si_model, input, _ = make_data_mimo_rbf
229
- # Compute jacobian using the chain rule and SMT.
230
- jacobian_si = si_model.predict_jacobian(input)
231
- # Compute jacobian using central finite differences.
232
- jacobian_fd = np.zeros(jacobian_si.shape)
233
- h = 1e-5
234
- for i in range(input.shape[1]):
235
- xm = input.copy()
236
- xp = input.copy()
237
- xm[:, i] -= h
238
- xp[:, i] += h
239
- jacobian_fd[:, :, i] = si_model.predict_output(xp) - si_model.predict_output(xm)
240
- jacobian_fd /= 2.0 * h
241
- npt.assert_allclose(jacobian_si, jacobian_fd, rtol=5e-7)
242
-
243
-
244
- def test_save_load_python(make_data_siso_krg):
245
- si_model, _, _ = make_data_siso_krg
246
- model_path = f"./{str(uuid.uuid4())}-model.h5"
247
- extra_data_path = f"./{str(uuid.uuid4())}-extra-data.h5"
248
- si_model.save_h5(model_path, extra_data_path)
249
- si_model_loaded = SMTModel.load_h5(model_path, extra_data_path)
250
- assert si_model == si_model_loaded
251
-
252
-
253
- def test_save_load_cpp(make_data_siso_rbf):
254
- si_model, _, _ = make_data_siso_rbf
255
- model_path = f"./{str(uuid.uuid4())}-model.h5"
256
- extra_data_path = f"./{str(uuid.uuid4())}-extra-data.h5"
257
- with pytest.raises(NotImplementedError):
258
- si_model.save_h5(model_path, extra_data_path)
@@ -1,22 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- import pytest
3
-
4
- from surrogates_interface.surrogates import SurrogateModel
5
-
6
-
7
- def test__save_model():
8
- obj = SurrogateModel(lambda x: x + 2.0)
9
- with pytest.raises(NotImplementedError):
10
- obj._save_model("file")
11
-
12
-
13
- def test__load_model():
14
- obj = SurrogateModel(lambda x: x + 2.0)
15
- with pytest.raises(NotImplementedError):
16
- obj._load_model("file")
17
-
18
-
19
- def test__predict_model_jacobian():
20
- obj = SurrogateModel(lambda x: x + 2.0)
21
- with pytest.raises(NotImplementedError):
22
- obj._predict_model_jacobian(1.0)