-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
72 changed files
with
6,970 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
*.pyc | ||
__pycache__ | ||
.project | ||
.pydevproject | ||
.settings/ | ||
coverage.xml | ||
nosetests.xml | ||
.coverage | ||
xdsm.html | ||
build/ | ||
dist/ | ||
/.pytest_cache/ | ||
/sostrades_optimization_plugins/tests/__pycache__/ | ||
/sostrades_optimization_plugins/tests/.pytest_cache/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# sostrades-optimization-plugin |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
{ | ||
"extension_to_ignore": [ | ||
"pkl", | ||
"png", | ||
"jpg", | ||
"csv", | ||
"md", | ||
"markdown", | ||
"avif", | ||
"json", | ||
"in", | ||
"gitignore", | ||
"cfg", | ||
"puml", | ||
"pdf", | ||
"txt", | ||
"ipynb", | ||
"zip", | ||
"rst", | ||
"ini", | ||
"coveragerc", | ||
"yaml", | ||
"bat", | ||
"tex", | ||
"toml" | ||
], | ||
"files_to_ignore": [ | ||
"LICENSE", | ||
".readthedocs", | ||
"docs/Makefile", | ||
".flake8", | ||
".prettierignore", | ||
"sostrades_optimization_plugins/models/design_var/design_var.py", | ||
"sostrades_optimization_plugins/models/design_var/design_var_disc.py", | ||
"sostrades_optimization_plugins/models/func_manager/func_manager.py", | ||
"sostrades_optimization_plugins/models/func_manager/func_manager_disc.py", | ||
"sostrades_optimization_plugins/sos_processes/test/test_sellar_opt_w_design_var/__init__.py", | ||
"sostrades_optimization_plugins/sos_processes/test/test_sellar_opt_w_design_var/process.py", | ||
"sostrades_optimization_plugins/sos_processes/test/test_sellar_opt_w_design_var/usecase.py", | ||
"sostrades_optimization_plugins/sos_processes/test/test_sellar_opt_w_func_manager/__init__.py", | ||
"sostrades_optimization_plugins/sos_processes/test/test_sellar_opt_w_func_manager/process.py", | ||
"sostrades_optimization_plugins/sos_processes/test/test_sellar_opt_w_func_manager/usecase.py", | ||
"sostrades_optimization_plugins/sos_processes/test/test_sellar_opt_w_func_manager_faulty/__init__.py", | ||
"sostrades_optimization_plugins/sos_processes/test/test_sellar_opt_w_func_manager_faulty/process.py", | ||
"sostrades_optimization_plugins/sos_processes/test/test_sellar_opt_w_func_manager_faulty/usecase.py", | ||
"sostrades_optimization_plugins/tests/l0_test_14_optim_scenario_with_func_manager.py", | ||
"sostrades_optimization_plugins/tests/l0_test_44_func_manager.py", | ||
"sostrades_optimization_plugins/tests/l0_test_62_design_var_in_sellar.py", | ||
"sostrades_optimization_plugins/tests/l1s_test_all_usecases.py", | ||
"sostrades_optimization_plugins/tools/cst_manager/common_config.py", | ||
"sostrades_optimization_plugins/tools/cst_manager/constraint_manager.py", | ||
"sostrades_optimization_plugins/tools/cst_manager/constraint_object.py", | ||
"sostrades_optimization_plugins/tools/cst_manager/database.py", | ||
"sostrades_optimization_plugins/tools/cst_manager/fileutils.py", | ||
"sostrades_optimization_plugins/tools/cst_manager/func_manager_common.py", | ||
"sostrades_optimization_plugins/tools/cst_manager/__init__.py" | ||
], | ||
"airbus_rev_commit": "d833fdf740389587b876e30f084631430687fa5a" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
v4.1.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
[pytest] | ||
python_files = l*_test*.py | ||
testpaths = | ||
sostrades_optimization_plugins/tests | ||
addopts = --numprocesses=auto |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
numpy==1.24.4 | ||
pandas==2.2.2 | ||
plotly==5.3.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
[lint] | ||
select = ["I", "TCH", "PLC", "PLE", "F", "E", "W", "PERF"] | ||
# extend-select = ["ALL"] | ||
|
||
ignore = ["E722", "F841", "E501", "D400", "D415", "D212", "D300", "PERF203", "ANN101"] | ||
# E722 Do not use bare `except` | ||
# F841 Local variable `xxx` is assigned to but never used | ||
# E501 Line too long | ||
# D400 First line should end with a period | ||
# D415 First line should end with a period, question mark, or exclamation point | ||
# D212 [*] Multi-line docstring summary should start at the first line | ||
# D300 [*] Use triple double quotes `"""` | ||
# ANN101 Missing type annotation for `self` in method |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
''' | ||
Copyright 2024 Capgemini | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
''' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
''' | ||
Copyright 2024 Capgemini | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
''' |
15 changes: 15 additions & 0 deletions
15
sostrades_optimization_plugins/models/design_var/__init__.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
''' | ||
Copyright 2024 Capgemini | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
''' |
199 changes: 199 additions & 0 deletions
199
sostrades_optimization_plugins/models/design_var/design_var.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,199 @@ | ||
''' | ||
Copyright 2022 Airbus SAS | ||
Modifications on 2023/07/25-2024/05/16 Copyright 2023 Capgemini | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
''' | ||
import numpy as np | ||
from pandas import DataFrame, concat | ||
from sostrades_core.execution_engine.sos_wrapp import SoSWrapp | ||
from sostrades_core.tools.bspline.bspline import BSpline | ||
|
||
|
||
class DesignVar(object): | ||
""" | ||
Class Design variable | ||
""" | ||
ACTIVATED_ELEM_LIST = "activated_elem" | ||
VARIABLES = "variable" | ||
VALUE = "value" | ||
DATAFRAME_FILL = SoSWrapp.DATAFRAME_FILL | ||
COLUMNS_NAMES = SoSWrapp.COLUMNS_NAMES | ||
ONE_COLUMN_PER_KEY = "one column per key" # FIXME: on 4.0.3 --> SoSWrapp.ONE_COLUMN_PER_KEY | ||
ONE_COLUMN_FOR_KEY = SoSWrapp.ONE_COLUMN_FOR_KEY | ||
DATAFRAME_FILL_POSSIBLE_VALUES = [ONE_COLUMN_PER_KEY, ONE_COLUMN_FOR_KEY] | ||
DESIGN_SPACE = 'design_space' | ||
DESIGN_VAR_DESCRIPTOR = 'design_var_descriptor' | ||
INDEX = 'index' | ||
INDEX_NAME = 'index_name' | ||
OUT_TYPE = 'out_type' | ||
OUT_NAME = 'out_name' | ||
FILL_ACTIVATED_ELEMENTS = 'fill_activated_elements' | ||
LAST_ELEMENT_ACTIVATED = 'last element activated' | ||
INITIAL_VALUE = 'initial_value' | ||
FILL_ACTIVATED_ELEMENTS_POSSIBLE_VALUES = [LAST_ELEMENT_ACTIVATED, INITIAL_VALUE] | ||
|
||
def __init__(self, inputs_dict, logger): | ||
''' | ||
Constructor | ||
''' | ||
self.design_var_descriptor = inputs_dict[self.DESIGN_VAR_DESCRIPTOR] | ||
self.output_dict = {} | ||
self.bspline_dict = {} | ||
self.dspace = inputs_dict[self.DESIGN_SPACE] | ||
self.logger = logger | ||
|
||
def configure(self, inputs_dict): | ||
''' | ||
Configure with inputs_dict from the discipline | ||
''' | ||
|
||
self.output_dict = {} | ||
list_ctrl = self.design_var_descriptor.keys() | ||
|
||
for elem in list_ctrl: | ||
l_activated = self.dspace.loc[self.dspace[self.VARIABLES] | ||
== elem, self.ACTIVATED_ELEM_LIST].to_list()[0] | ||
# check output length and compute BSpline only if necessary | ||
# remark: float do not require any BSpline usage | ||
output_length = len(self.design_var_descriptor[elem][self.INDEX]) | ||
deactivated_elem_flag = not all(l_activated) | ||
if deactivated_elem_flag: | ||
final_value, gradient = self.rebuild_input_array_with_activated_elements(inputs_dict, elem) | ||
else: | ||
final_value = inputs_dict[elem] | ||
gradient = np.identity(output_length) | ||
|
||
if len(final_value) == output_length: | ||
self.bspline_dict[elem] = { | ||
'bspline': None, 'eval_t': final_value, 'b_array': gradient} | ||
else: | ||
self.create_array_with_bspline(elem, final_value, output_length, | ||
deactivated_elem_flag) | ||
|
||
# loop over design_var_descriptor to build output | ||
self.build_output_with_design_var_descriptor(elem, final_value) | ||
|
||
def create_array_with_bspline(self, elem, final_value, output_length, deactivated_elem_flag): | ||
|
||
list_t = np.linspace(0.0, 1.0, output_length) | ||
bspline = BSpline(n_poles=len(final_value)) | ||
bspline.set_ctrl_pts(final_value) | ||
eval_t, b_array = bspline.eval_list_t(list_t) | ||
b_array = bspline.update_b_array(b_array) | ||
if deactivated_elem_flag: | ||
b_array = self.update_gradient_with_deactivated_elements_first_value(b_array) | ||
self.bspline_dict[elem] = { | ||
'bspline': bspline, 'eval_t': eval_t, 'b_array': b_array} | ||
|
||
def rebuild_input_array_with_activated_elements(self, inputs_dict, elem): | ||
''' | ||
If some elements are desactivated wit the option activated_elem in design space, the function rebuild the correct array depending on the method | ||
''' | ||
# checks that dspace and activated elements are coherent with input element size | ||
l_activated = self.dspace.loc[self.dspace[self.VARIABLES] | ||
== elem, self.ACTIVATED_ELEM_LIST].to_list()[0] | ||
|
||
elem_input_value = list(inputs_dict[elem]) | ||
input_length = len(elem_input_value) | ||
if sum(l_activated) != input_length: | ||
self.logger.error( | ||
f'The size of the input element {elem} is not coherent with the design space and its activated elements : {sum(l_activated)} activated elements and elem of length {len(elem_input_value)}') | ||
|
||
final_value = [] | ||
# TODO compute the gradient for each case | ||
gradient = [] | ||
initial_gradient = np.identity(input_length).tolist() | ||
# We fill deactivated elements with the last element activated in the array | ||
if self.FILL_ACTIVATED_ELEMENTS in self.design_var_descriptor[elem] and self.design_var_descriptor[elem][ | ||
self.FILL_ACTIVATED_ELEMENTS] == self.LAST_ELEMENT_ACTIVATED: | ||
|
||
for activated_bool in l_activated: | ||
if activated_bool: | ||
gradient.append(initial_gradient.pop(0)) | ||
final_value.append(elem_input_value.pop(0)) | ||
else: | ||
final_value.append(final_value[-1]) | ||
# TODO gradient is not null but depend on last value | ||
# need to fix it | ||
gradient.append([0.] * input_length) | ||
# by default we use initial value to fill the deactivated elements | ||
else: | ||
initial_value = self.dspace.loc[self.dspace[self.VARIABLES] | ||
== elem, self.VALUE].to_list()[0] | ||
|
||
for i, activated_bool in enumerate(l_activated): | ||
if activated_bool: | ||
final_value.append(elem_input_value.pop(0)) | ||
gradient.append(initial_gradient.pop(0)) | ||
else: | ||
final_value.append(initial_value[i]) | ||
gradient.append([0.] * input_length) | ||
return np.array(final_value), np.array(gradient) | ||
|
||
def update_gradient_with_deactivated_elements_first_value(self, initial_gradient): | ||
### TO DO generalize it with other deactivated elements | ||
|
||
result = np.delete(initial_gradient, 0, axis=1) | ||
return result | ||
|
||
def build_output_with_design_var_descriptor(self, elem, final_value): | ||
|
||
out_name = self.design_var_descriptor[elem][self.OUT_NAME] | ||
out_type = self.design_var_descriptor[elem][self.OUT_TYPE] | ||
|
||
if out_type == 'float': | ||
if final_value.size != 1: | ||
raise ValueError(" The input must be of size 1 for a float output") | ||
self.output_dict[out_name] = final_value[0] | ||
elif out_type == 'array': | ||
self.output_dict[out_name] = self.bspline_dict[elem]['eval_t'] | ||
elif out_type == 'dataframe': | ||
# dataframe fill is optional ,by default we fill the dataframe with one column per key | ||
if self.DATAFRAME_FILL in self.design_var_descriptor[elem]: | ||
dataframe_fill = self.design_var_descriptor[elem][self.DATAFRAME_FILL] | ||
else: | ||
dataframe_fill = self.ONE_COLUMN_PER_KEY | ||
index = self.design_var_descriptor[elem][self.INDEX] | ||
index_name = self.design_var_descriptor[elem][self.INDEX_NAME] | ||
if dataframe_fill == self.ONE_COLUMN_PER_KEY: | ||
# for the method one column per key we create a dataframe if it does not exists | ||
if self.design_var_descriptor[elem][self.OUT_NAME] not in self.output_dict.keys(): | ||
# init output dataframes with index | ||
|
||
self.output_dict[out_name] = DataFrame({index_name: index}) | ||
# we use the key 'key' in the design_var_descriptor for the name of the column and the column to the dataframe | ||
col_name = self.design_var_descriptor[elem]['key'] | ||
self.output_dict[out_name][col_name] = self.bspline_dict[elem]['eval_t'] | ||
elif dataframe_fill == self.ONE_COLUMN_FOR_KEY: | ||
|
||
column_names = self.design_var_descriptor[elem][self.COLUMNS_NAMES] | ||
# # create a dataframe using column_names, in this method the dataframe will ALWAYS have 2 columns | ||
# first column will store the key | ||
# second column the value | ||
|
||
df_to_merge = DataFrame( | ||
{index_name: index, | ||
column_names[0]: self.design_var_descriptor[elem]['key'], | ||
column_names[1]: self.bspline_dict[elem]['eval_t']}) | ||
# if the dataframe still not exists werite it | ||
if self.design_var_descriptor[elem][self.OUT_NAME] not in self.output_dict.keys(): | ||
self.output_dict[out_name] = df_to_merge | ||
# if it exists, concatenate it in order to have multiple lines in the dataframe for each key | ||
else: | ||
self.output_dict[out_name] = concat([self.output_dict[out_name], df_to_merge], | ||
ignore_index=True) | ||
else: | ||
raise (ValueError('Output type not yet supported')) |
Oops, something went wrong.