gemseo-multi-fidelity 0.0.1__py3-none-any.whl

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.
Files changed (76) hide show
  1. gemseo_multi_fidelity/__init__.py +17 -0
  2. gemseo_multi_fidelity/core/MFMapperAdapter_input.json +22 -0
  3. gemseo_multi_fidelity/core/MFMapperAdapter_output.json +22 -0
  4. gemseo_multi_fidelity/core/MFMapperLinker_input.json +22 -0
  5. gemseo_multi_fidelity/core/MFMapperLinker_output.json +22 -0
  6. gemseo_multi_fidelity/core/MFScenarioAdapter_input.json +39 -0
  7. gemseo_multi_fidelity/core/MFScenarioAdapter_output.json +23 -0
  8. gemseo_multi_fidelity/core/__init__.py +16 -0
  9. gemseo_multi_fidelity/core/boxed_domain.py +242 -0
  10. gemseo_multi_fidelity/core/corr_function.py +411 -0
  11. gemseo_multi_fidelity/core/criticality.py +124 -0
  12. gemseo_multi_fidelity/core/ds_mapper.py +307 -0
  13. gemseo_multi_fidelity/core/errors.py +42 -0
  14. gemseo_multi_fidelity/core/eval_mapper.py +188 -0
  15. gemseo_multi_fidelity/core/id_mapper_adapter.py +61 -0
  16. gemseo_multi_fidelity/core/mapper_adapter.py +126 -0
  17. gemseo_multi_fidelity/core/mapper_linker.py +72 -0
  18. gemseo_multi_fidelity/core/mf_formulation.py +635 -0
  19. gemseo_multi_fidelity/core/mf_logger.py +216 -0
  20. gemseo_multi_fidelity/core/mf_opt_problem.py +480 -0
  21. gemseo_multi_fidelity/core/mf_scenario.py +205 -0
  22. gemseo_multi_fidelity/core/noise_criterion.py +94 -0
  23. gemseo_multi_fidelity/core/projpolytope.out +0 -0
  24. gemseo_multi_fidelity/core/scenario_adapter.py +568 -0
  25. gemseo_multi_fidelity/core/stop_criteria.py +201 -0
  26. gemseo_multi_fidelity/core/strict_chain.py +75 -0
  27. gemseo_multi_fidelity/core/utils_model_quality.py +74 -0
  28. gemseo_multi_fidelity/corrections/__init__.py +16 -0
  29. gemseo_multi_fidelity/corrections/add_corr_function.py +80 -0
  30. gemseo_multi_fidelity/corrections/correction_factory.py +65 -0
  31. gemseo_multi_fidelity/corrections/mul_corr_function.py +86 -0
  32. gemseo_multi_fidelity/drivers/__init__.py +16 -0
  33. gemseo_multi_fidelity/drivers/mf_algo_factory.py +38 -0
  34. gemseo_multi_fidelity/drivers/mf_driver_lib.py +462 -0
  35. gemseo_multi_fidelity/drivers/refinement.py +234 -0
  36. gemseo_multi_fidelity/drivers/settings/__init__.py +16 -0
  37. gemseo_multi_fidelity/drivers/settings/base_mf_driver_settings.py +59 -0
  38. gemseo_multi_fidelity/drivers/settings/mf_refine_settings.py +50 -0
  39. gemseo_multi_fidelity/formulations/__init__.py +16 -0
  40. gemseo_multi_fidelity/formulations/refinement.py +144 -0
  41. gemseo_multi_fidelity/mapping/__init__.py +16 -0
  42. gemseo_multi_fidelity/mapping/identity_mapper.py +74 -0
  43. gemseo_multi_fidelity/mapping/interp_mapper.py +422 -0
  44. gemseo_multi_fidelity/mapping/mapper_factory.py +70 -0
  45. gemseo_multi_fidelity/mapping/mapping_errors.py +46 -0
  46. gemseo_multi_fidelity/mapping/subset_mapper.py +122 -0
  47. gemseo_multi_fidelity/mf_rosenbrock/__init__.py +16 -0
  48. gemseo_multi_fidelity/mf_rosenbrock/delayed_disc.py +136 -0
  49. gemseo_multi_fidelity/mf_rosenbrock/refact_rosen_testcase.py +46 -0
  50. gemseo_multi_fidelity/mf_rosenbrock/rosen_mf_case.py +284 -0
  51. gemseo_multi_fidelity/mf_rosenbrock/rosen_mf_funcs.py +350 -0
  52. gemseo_multi_fidelity/models/__init__.py +16 -0
  53. gemseo_multi_fidelity/models/fake_updater.py +112 -0
  54. gemseo_multi_fidelity/models/model_updater.py +91 -0
  55. gemseo_multi_fidelity/models/rbf/__init__.py +16 -0
  56. gemseo_multi_fidelity/models/rbf/kernel_factory.py +66 -0
  57. gemseo_multi_fidelity/models/rbf/kernels/__init__.py +16 -0
  58. gemseo_multi_fidelity/models/rbf/kernels/gaussian.py +93 -0
  59. gemseo_multi_fidelity/models/rbf/kernels/matern_3_2.py +101 -0
  60. gemseo_multi_fidelity/models/rbf/kernels/matern_5_2.py +101 -0
  61. gemseo_multi_fidelity/models/rbf/kernels/rbf_kernel.py +172 -0
  62. gemseo_multi_fidelity/models/rbf/rbf_model.py +422 -0
  63. gemseo_multi_fidelity/models/sparse_rbf_updater.py +96 -0
  64. gemseo_multi_fidelity/models/taylor/__init__.py +16 -0
  65. gemseo_multi_fidelity/models/taylor/taylor.py +212 -0
  66. gemseo_multi_fidelity/models/taylor_updater.py +66 -0
  67. gemseo_multi_fidelity/models/updater_factory.py +62 -0
  68. gemseo_multi_fidelity/settings/__init__.py +16 -0
  69. gemseo_multi_fidelity/settings/drivers.py +22 -0
  70. gemseo_multi_fidelity/settings/formulations.py +16 -0
  71. gemseo_multi_fidelity-0.0.1.dist-info/METADATA +99 -0
  72. gemseo_multi_fidelity-0.0.1.dist-info/RECORD +76 -0
  73. gemseo_multi_fidelity-0.0.1.dist-info/WHEEL +5 -0
  74. gemseo_multi_fidelity-0.0.1.dist-info/entry_points.txt +2 -0
  75. gemseo_multi_fidelity-0.0.1.dist-info/licenses/LICENSE.txt +165 -0
  76. gemseo_multi_fidelity-0.0.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,307 @@
1
+ # Copyright 2021 IRT Saint Exupéry, https://www.irt-saintexupery.com
2
+ #
3
+ # This program is free software; you can redistribute it and/or
4
+ # modify it under the terms of the GNU Lesser General Public
5
+ # License version 3 as published by the Free Software Foundation.
6
+ #
7
+ # This program is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10
+ # Lesser General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU Lesser General Public License
13
+ # along with this program; if not, write to the Free Software Foundation,
14
+ # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15
+
16
+ # Copyright (c) 2019 AIRBUS OPERATIONS
17
+
18
+ #
19
+ # Contributors:
20
+ # INITIAL AUTHORS - API and implementation and/or documentation
21
+ # :author: Romain Olivanti
22
+ # OTHER AUTHORS - MACROSCOPIC CHANGES
23
+ """Base class for design space mapping."""
24
+
25
+ from __future__ import annotations
26
+
27
+ from collections.abc import Mapping
28
+ from typing import TYPE_CHECKING
29
+ from typing import Any
30
+
31
+ from gemseo.algos.design_space import DesignSpace
32
+ from numpy import abs as np_abs
33
+ from numpy import arange
34
+ from numpy import ndarray
35
+ from numpy import zeros
36
+
37
+ if TYPE_CHECKING:
38
+ from collections.abc import Iterable
39
+
40
+ from numpy.typing import NDArray
41
+
42
+ try:
43
+ import matplotlib.gridspec as gridspec
44
+ import pylab
45
+ # from matplotlib.cm import seismic
46
+
47
+ PLOT_AVAILABLE = True
48
+ except ImportError:
49
+ PLOT_AVAILABLE = False
50
+
51
+
52
+ class DesignSpaceMapper:
53
+ """Abstract class for design space mapping."""
54
+
55
+ def __init__(
56
+ self, design_space_in: DesignSpace, design_space_out: DesignSpace
57
+ ) -> None:
58
+ """
59
+ Args:
60
+ design_space_in: The input ``DesignSpace`` object.
61
+ design_space_out: The output ``DesignSpace`` object.
62
+ """ # noqa: D205 D212 D415
63
+ self._check_design_space(design_space_in, design_space_out)
64
+ self.design_space_in = design_space_in
65
+ self.design_space_out = design_space_out
66
+
67
+ @staticmethod
68
+ def _check_design_space(ds_in, ds_out):
69
+ if not isinstance(ds_in, DesignSpace):
70
+ msg = "design_space_in must be an instance of DesignSpace"
71
+ raise TypeError(msg)
72
+ if not isinstance(ds_out, DesignSpace):
73
+ msg = "design_space_out must be an instance of DesignSpace"
74
+ raise TypeError(msg)
75
+
76
+ def _map_vars_direct(self, dvs_dict_in: DesignSpace):
77
+ """Real direct mapping routine. To be overloaded by subclasses."""
78
+ raise NotImplementedError
79
+
80
+ def _map_vars_reverse(self, dvs_dict_out: DesignSpace):
81
+ """Real reverse mapping routine. To be overloaded by subclasses."""
82
+ raise NotImplementedError
83
+
84
+ def _map_vars(
85
+ self,
86
+ dvs: Mapping[str, Any] | NDArray,
87
+ to_array: bool = True,
88
+ direct: bool = True,
89
+ ) -> Mapping[str, Any] | NDArray:
90
+ """Take care of formating inputs/outputs using the DesignSpace API.
91
+
92
+ The real mapping is performed in _map_vars_direct and _map_vars_reverse.
93
+
94
+ Args:
95
+ dvs: The variables to map.
96
+ to_array: The flag to specify if a dict or an array should be returned as
97
+ output.
98
+ direct: The flag to indicate if the mapping must be performed in the direct
99
+ or reverse order.
100
+
101
+ Returns:
102
+ The mapping.
103
+ """
104
+ # Reverse if needed
105
+ if direct:
106
+ ds_in = self.design_space_in
107
+ ds_out = self.design_space_out
108
+ map_method = self._map_vars_direct
109
+ else:
110
+ ds_in = self.design_space_out
111
+ ds_out = self.design_space_in
112
+ map_method = self._map_vars_reverse
113
+
114
+ # Make sure the input is a dict
115
+ if isinstance(dvs, Mapping):
116
+ dvs_in_dict = dvs
117
+ elif isinstance(dvs, ndarray):
118
+ dvs_in_dict = ds_in.convert_array_to_dict(dvs)
119
+ else:
120
+ raise TypeError("Unsupported DV type " + str(type(dvs)))
121
+ dvs_out = map_method(dvs_in_dict)
122
+ if to_array:
123
+ dvs_out = ds_out.convert_dict_to_array(dvs_out)
124
+ return dvs_out
125
+
126
+ def map_vars_direct(
127
+ self, dvs_in: Mapping[str, Any] | NDArray, to_array: bool = False
128
+ ) -> Mapping[str, Any] | NDArray:
129
+ """Map the provided design variables from in to out.
130
+
131
+ Args:
132
+ dvs_in: The design variables from the input design space.
133
+ to_array: The flag to specify if a dict or an array should be returned as
134
+ output.
135
+
136
+ Returns:
137
+ The design variables in the output design space either dict or array
138
+ depending on the ``to_array`` flag.
139
+ """
140
+ return self._map_vars(dvs_in, to_array=to_array, direct=True)
141
+
142
+ def map_vars_reverse(
143
+ self, dvs_out: Mapping[str, Any] | NDArray, to_array: bool = False
144
+ ) -> Mapping[str, Any] | NDArray:
145
+ """Map the provided design variables from out to in.
146
+
147
+ Args:
148
+ dvs_out: The design variables from the output design space.
149
+ to_array: The flag to specify if a dict or an array should be returned as
150
+ output.
151
+
152
+ Returns:
153
+ The design variables in the input design space either dict or array
154
+ depending on the ``to_array`` flag.
155
+ """
156
+ return self._map_vars(dvs_out, to_array=to_array, direct=False)
157
+
158
+ def has_reverse(self) -> bool:
159
+ """Check if the mapper can perform the reverse mapping.
160
+
161
+ Returns:
162
+ ``True`` if reverse mapping can be performed.
163
+ """
164
+ is_reverse_implemented = True
165
+ try:
166
+ self.map_vars_reverse(self.design_space_out.get_current_value(as_dict=True))
167
+ except NotImplementedError:
168
+ is_reverse_implemented = False
169
+ return is_reverse_implemented
170
+
171
+ def _map_ds(self, direct: bool = True):
172
+ """Map the design spaces directly.
173
+
174
+ Args:
175
+ direct: ``True`` for direct mode, ``False`` for the reverse mode.
176
+ """
177
+ if direct:
178
+ ds_in = self.design_space_in
179
+ ds_out = self.design_space_out
180
+ map_method = self.map_vars_direct
181
+ else:
182
+ ds_in = self.design_space_out
183
+ ds_out = self.design_space_in
184
+ map_method = self.map_vars_reverse
185
+
186
+ x_in = ds_in.get_current_value(as_dict=True)
187
+ x_out = map_method(x_in, to_array=True)
188
+ # Make sure the new current x fits in the design space
189
+ x_out = ds_out.project_into_bounds(x_out, normalized=False)
190
+ ds_out.set_current_value(x_out)
191
+
192
+ def map_ds_direct(self) -> None:
193
+ """Map the design spaces from in to out."""
194
+ self._map_ds(direct=True)
195
+
196
+ def map_ds_reverse(self) -> None:
197
+ """Map the design spaces from out to in."""
198
+ self._map_ds(direct=False)
199
+
200
+ def get_jac(self) -> dict:
201
+ """Get the jacobian of the mapper (direct).
202
+
203
+ Returns:
204
+ The jacobian.
205
+ """
206
+ raise NotImplementedError
207
+
208
+ def get_jac_array(self) -> tuple[NDArray, Iterable[str], Iterable[str]]:
209
+ """Return an array of the mapper jacobian with the associated variables names.
210
+
211
+ Returns:
212
+ The tuple (jacobian, vars_in, vars_out).
213
+ """
214
+ ds_out = self.design_space_out
215
+ ds_in = self.design_space_in
216
+
217
+ # Prepare the labels depending on the sizes
218
+ vars_out = []
219
+ vars_in = []
220
+ map_vars_out_to_indexes = {}
221
+ map_vars_in_to_indexes = {}
222
+
223
+ for vars_list, ds, map_inds in zip(
224
+ [vars_out, vars_in],
225
+ [ds_out, ds_in],
226
+ [map_vars_out_to_indexes, map_vars_in_to_indexes],
227
+ strict=False,
228
+ ):
229
+ i_curr = 0
230
+ for var in ds.variable_names:
231
+ var_size = int(ds.get_size(var))
232
+ if var_size == 1:
233
+ vars_list += [var]
234
+ else:
235
+ vars_list += [f"{var}_{i:d}" for i in range(int(var_size))]
236
+ map_inds[var] = [i_curr, i_curr + var_size]
237
+ i_curr += var_size
238
+
239
+ # Build the jacobian array
240
+ jac_array = zeros((len(vars_out), len(vars_in)))
241
+ jac_dict = self.get_jac()
242
+
243
+ for var_out, jac_link in iter(list(jac_dict.items())):
244
+ i_start, i_end = map_vars_out_to_indexes[var_out]
245
+ for var_in, sub_array in iter(list(jac_link.items())):
246
+ j_start, j_end = map_vars_in_to_indexes[var_in]
247
+ jac_array[i_start:i_end, j_start:j_end] = sub_array
248
+
249
+ return jac_array, vars_in, vars_out
250
+
251
+ def plot_jac(self) -> None:
252
+ """Plot the mapping jacobian using pylab.
253
+
254
+ If pylab is not available, no output is produced.
255
+ """
256
+ if not PLOT_AVAILABLE:
257
+ return
258
+
259
+ jac_array, vars_in, vars_out = self.get_jac_array()
260
+
261
+ # Build the figure
262
+ max_value = np_abs(jac_array).max()
263
+
264
+ fig = pylab.plt.figure(figsize=(8, 8), dpi=80, facecolor="w", edgecolor="k")
265
+ grid = gridspec.GridSpec(
266
+ 2, 2, width_ratios=[10, 1], height_ratios=[10, 1], wspace=0.04, hspace=0.2
267
+ )
268
+ ax1 = fig.add_subplot(grid[0, 0])
269
+ ax1.set_xlabel("variables in", labelpad=10, rotation="horizontal", size=12)
270
+ ax1.set_ylabel("variables out", labelpad=10, rotation="vertical", size=12)
271
+ # Set the title
272
+ ax1.set_title("Mapper jacobian")
273
+
274
+ # Plot the data
275
+ im = ax1.imshow(
276
+ jac_array / max_value,
277
+ cmap="seismic",
278
+ vmin=-1,
279
+ vmax=1.0,
280
+ interpolation="nearest",
281
+ aspect="auto",
282
+ )
283
+
284
+ ax1.set_yticklabels(vars_out)
285
+ ax1.set_yticks(arange(jac_array.shape[0]))
286
+ ax1.set_xticklabels(vars_in)
287
+ ax1.set_xticks(arange(jac_array.shape[1]))
288
+
289
+ # Custom colorbar
290
+ ax2 = fig.add_subplot(grid[0, 1])
291
+ pylab.plt.colorbar(im, cax=ax2)
292
+
293
+ # Set window size
294
+ mng = pylab.plt.get_current_fig_manager()
295
+ mng.resize(700, 1000)
296
+ pylab.plt.show()
297
+
298
+ def __str__(self) -> str:
299
+ """Textual representation of the DesignSpaceMapper.
300
+
301
+ Returns:
302
+ The textual representation.
303
+ """
304
+ ds_in = self.design_space_in
305
+ ds_out = self.design_space_out
306
+ class_name = self.__class__.__name__
307
+ return f"{class_name}\n\n{ds_in}\n\n-- (direct) -->\n\n{ds_out}"
@@ -0,0 +1,42 @@
1
+ # Copyright 2021 IRT Saint Exupéry, https://www.irt-saintexupery.com
2
+ #
3
+ # This program is free software; you can redistribute it and/or
4
+ # modify it under the terms of the GNU Lesser General Public
5
+ # License version 3 as published by the Free Software Foundation.
6
+ #
7
+ # This program is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10
+ # Lesser General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU Lesser General Public License
13
+ # along with this program; if not, write to the Free Software Foundation,
14
+ # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15
+
16
+ # Copyright (c) 2018 AIRBUS OPERATIONS
17
+
18
+ #
19
+ # Contributors:
20
+ # INITIAL AUTHORS - API and implementation and/or documentation
21
+ # :author: Romain Olivanti
22
+ # OTHER AUTHORS - MACROSCOPIC CHANGES
23
+ """Errors."""
24
+
25
+ from __future__ import annotations
26
+
27
+
28
+ class ConsistencyError(Exception):
29
+ """Consistency error."""
30
+
31
+ def __init__(self, msg: str) -> None:
32
+ """Constructor.
33
+
34
+ Args:
35
+ msg: The explanation for the inconsistency.
36
+ """
37
+ super().__init__()
38
+ self.msg = msg
39
+
40
+ def __str__(self) -> str:
41
+ """Custom string representation."""
42
+ return repr(self.msg)
@@ -0,0 +1,188 @@
1
+ # Copyright 2021 IRT Saint Exupéry, https://www.irt-saintexupery.com
2
+ #
3
+ # This program is free software; you can redistribute it and/or
4
+ # modify it under the terms of the GNU Lesser General Public
5
+ # License version 3 as published by the Free Software Foundation.
6
+ #
7
+ # This program is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10
+ # Lesser General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU Lesser General Public License
13
+ # along with this program; if not, write to the Free Software Foundation,
14
+ # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15
+
16
+ # Copyright (c) 2019 AIRBUS OPERATIONS
17
+
18
+ #
19
+ # Contributors:
20
+ # INITIAL AUTHORS - API and implementation and/or documentation
21
+ # :author: Romain Olivanti
22
+ # OTHER AUTHORS - MACROSCOPIC CHANGES
23
+ """Evaluation Mapper."""
24
+
25
+ from __future__ import annotations
26
+
27
+ from typing import TYPE_CHECKING
28
+
29
+ from gemseo.algos.database import Database
30
+
31
+ from gemseo_multi_fidelity.core.ds_mapper import DesignSpaceMapper
32
+
33
+ if TYPE_CHECKING:
34
+ from numpy.typing import NDArray
35
+
36
+
37
+ class EvaluationMapper:
38
+ """Object to perform the mapping of an evaluation between two levels."""
39
+
40
+ def __init__(
41
+ self,
42
+ ds_mapper: DesignSpaceMapper,
43
+ output_mapping: dict,
44
+ jac_tag: str = Database.GRAD_TAG,
45
+ ) -> None:
46
+ """Auto-detects jacobian inputs using the ``jac_tag`` prefix.
47
+
48
+ Args:
49
+ ds_mapper: The designer space mapper between the two levels.
50
+ output_mapping: The mapping (direct).
51
+ jac_tag: The prefix to identify jacobian data.
52
+ """
53
+ if not isinstance(ds_mapper, DesignSpaceMapper):
54
+ msg = "ds_mapper must be an instance of DesignSpaceMapper"
55
+ raise TypeError(msg)
56
+
57
+ if not isinstance(output_mapping, dict):
58
+ msg = "output_mapping must be a dict"
59
+ raise TypeError(msg)
60
+
61
+ if len(output_mapping) == 0:
62
+ msg = "output_mapping must not be empty"
63
+ raise ValueError(msg)
64
+
65
+ self.design_space_mapper = ds_mapper
66
+ self.output_mapping = output_mapping
67
+ self.jac_tag = jac_tag
68
+ self.reverse_output_mapping = self.build_reverse_output_mapping(output_mapping)
69
+
70
+ @staticmethod
71
+ def build_reverse_output_mapping(output_mapping: dict) -> dict:
72
+ """Build the reverse mapping.
73
+
74
+ Args:
75
+ output_mapping: The mapping of the functions in the direct order.
76
+
77
+ Returns:
78
+ The reverse mapping.
79
+ """
80
+ reverse_mapping = {}
81
+
82
+ for var_in, var_out in iter(list(output_mapping.items())):
83
+ # Must be strings
84
+ for v in [var_in, var_out]:
85
+ if not isinstance(v, str):
86
+ msg = f"{v} not a str"
87
+ raise TypeError(msg)
88
+ reverse_mapping[var_out] = var_in
89
+ return reverse_mapping
90
+
91
+ def _map_eval(
92
+ self,
93
+ dict_eval: dict,
94
+ x_eval: dict | NDArray = None,
95
+ to_arrays: bool = False,
96
+ direct: bool = True,
97
+ ) -> tuple[dict, NDArray]:
98
+ """Actual mapping routine.
99
+
100
+ Args:
101
+ dict_eval: The data to map.
102
+ x_eval: The variables linked to the data.
103
+ to_arrays: The flag to convert all dicts to arrays expressed in the output
104
+ space.
105
+ direct: ``True`` for the direct order.
106
+
107
+ Returns:
108
+ The tuple (data_mapped, x_mapped).
109
+ """
110
+ if direct:
111
+ map_vars = self.design_space_mapper.map_vars_direct
112
+ # TODO update with dedicated method
113
+ map_jac = self.design_space_mapper.map_vars_direct
114
+ output_mapping = self.output_mapping
115
+ else:
116
+ map_vars = self.design_space_mapper.map_vars_reverse
117
+ # TODO update with dedicated method
118
+ map_jac = self.design_space_mapper.map_vars_reverse
119
+ output_mapping = self.reverse_output_mapping
120
+
121
+ x_mapped = map_vars(x_eval, to_array=to_arrays) if x_eval is not None else None
122
+
123
+ dict_mapped = {}
124
+
125
+ for data_name, value in dict_eval.items():
126
+ # process all inputs, all known funcs will be mapped
127
+ if data_name.startswith(self.jac_tag):
128
+ is_jac = True
129
+ data_name = data_name.split(self.jac_tag)[-1]
130
+ else:
131
+ is_jac = False
132
+ try:
133
+ name_out = output_mapping[data_name]
134
+ if is_jac:
135
+ mapped_value = map_jac(value, to_array=to_arrays)
136
+ name_out = self.jac_tag + name_out
137
+ else:
138
+ mapped_value = value
139
+ dict_mapped[name_out] = mapped_value
140
+ except KeyError:
141
+ # Not an item that must be mapped
142
+ pass
143
+
144
+ return dict_mapped, x_mapped
145
+
146
+ def map_eval_direct(
147
+ self,
148
+ dict_eval: dict,
149
+ x_eval: dict | NDArray = None,
150
+ to_arrays: bool = False,
151
+ ) -> tuple[dict, NDArray]:
152
+ """Map the provided data (direct logic).
153
+
154
+ Args:
155
+ dict_eval: The data to map.
156
+ x_eval: The variables linked to the data, if ``None``, x_mapped will be
157
+ ``None``.
158
+ to_arrays: The flag to convert all dicts to arrays expressed in the output
159
+ space.
160
+
161
+ Returns:
162
+ The tuple (data_mapped, x_mapped).
163
+ """
164
+ return self._map_eval(
165
+ dict_eval, x_eval=x_eval, to_arrays=to_arrays, direct=True
166
+ )
167
+
168
+ def map_eval_reverse(
169
+ self,
170
+ dict_eval: dict,
171
+ x_eval: dict | NDArray = None,
172
+ to_arrays: bool = False,
173
+ ) -> tuple[dict, NDArray]:
174
+ """Map the provided data (reverse logic).
175
+
176
+ Args:
177
+ dict_eval: The data to map.
178
+ x_eval: The variables linked to the data, if ``None``, x_mapped will be
179
+ ``None``.
180
+ to_arrays: The flag to convert all dicts to arrays expressed in the input
181
+ space.
182
+
183
+ Returns:
184
+ The tuple (data_mapped, x_mapped).
185
+ """
186
+ return self._map_eval(
187
+ dict_eval, x_eval=x_eval, to_arrays=to_arrays, direct=False
188
+ )
@@ -0,0 +1,61 @@
1
+ # Copyright 2021 IRT Saint Exupéry, https://www.irt-saintexupery.com
2
+ #
3
+ # This program is free software; you can redistribute it and/or
4
+ # modify it under the terms of the GNU Lesser General Public
5
+ # License version 3 as published by the Free Software Foundation.
6
+ #
7
+ # This program is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10
+ # Lesser General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU Lesser General Public License
13
+ # along with this program; if not, write to the Free Software Foundation,
14
+ # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15
+
16
+ # Copyright (c) 2019 AIRBUS OPERATIONS
17
+
18
+ #
19
+ # Contributors:
20
+ # INITIAL AUTHORS - API and implementation and/or documentation
21
+ # :author: Romain Olivanti
22
+ # OTHER AUTHORS - MACROSCOPIC CHANGES
23
+ """Convenience adapter.
24
+
25
+ To map the output of a sub-optimization in the same design space.
26
+ """
27
+
28
+ from __future__ import annotations
29
+
30
+ from gemseo_multi_fidelity.core.mapper_adapter import MFMapperAdapter
31
+ from gemseo_multi_fidelity.core.scenario_adapter import MFScenarioAdapter
32
+
33
+
34
+ class MFIdMapperAdapter(MFMapperAdapter):
35
+ """Multi-fidelity identity mapper adapter."""
36
+
37
+ def __init__(self, name: str, direct: bool = True) -> None:
38
+ """Constructor.
39
+
40
+ Args:
41
+ name: The name of the adapter.
42
+ direct: Whether it is direct.
43
+ """
44
+ # Do not call the super of MFIdMapperAdapter as the evaluation mapper
45
+ # is checked
46
+ super(MFMapperAdapter, self).__init__(name=name)
47
+
48
+ if not isinstance(direct, bool):
49
+ msg = "direct must be a boolean"
50
+ raise TypeError(msg)
51
+
52
+ self._is_direct = direct
53
+ super()._init_grammars(self.__class__.__base__.__name__)
54
+
55
+ def _map_x_best(self) -> None:
56
+ """Map the output best point as the next starting point."""
57
+ x_in = self.io.data[MFScenarioAdapter.X_BEST]
58
+ self.io.data[MFScenarioAdapter.X_START] = x_in
59
+
60
+ def _map_reference_data(self) -> None:
61
+ """Map the reference data, filters out reference data in direct mode."""