pyfemtet 0.9.5__py3-none-any.whl → 1.0.0b0__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.
Potentially problematic release.
This version of pyfemtet might be problematic. Click here for more details.
- pyfemtet/__init__.py +6 -1
- pyfemtet/_i18n/1. make_pot_and_update_po.bat +8 -0
- pyfemtet/_i18n/2. build_mo.bat +5 -0
- pyfemtet/_i18n/__init__.py +4 -0
- pyfemtet/_i18n/babel.cfg +2 -0
- pyfemtet/_i18n/i18n.py +37 -0
- pyfemtet/_i18n/locales/ja/LC_MESSAGES/messages.mo +0 -0
- pyfemtet/_i18n/locales/ja/LC_MESSAGES/messages.po +1020 -0
- pyfemtet/_i18n/locales/messages.pot +987 -0
- pyfemtet/{_message → _i18n}/messages.py +128 -41
- pyfemtet/_util/closing.py +19 -0
- pyfemtet/_util/dask_util.py +89 -7
- pyfemtet/_util/df_util.py +29 -0
- pyfemtet/_util/excel_macro_util.py +8 -3
- pyfemtet/_util/excel_parse_util.py +43 -23
- pyfemtet/_util/femtet_access_inspection.py +120 -0
- pyfemtet/{_femtet_config_util/autosave.py → _util/femtet_autosave.py} +7 -0
- pyfemtet/_util/femtet_exit.py +105 -0
- pyfemtet/_util/femtet_version.py +20 -0
- pyfemtet/_util/helper.py +94 -0
- pyfemtet/_util/process_util.py +107 -0
- pyfemtet/_util/str_enum.py +44 -0
- pyfemtet/core.py +15 -47
- pyfemtet/dispatch_extensions/__init__.py +8 -11
- pyfemtet/dispatch_extensions/_impl.py +42 -198
- pyfemtet/logger/__init__.py +8 -1
- pyfemtet/logger/_impl.py +5 -6
- pyfemtet/opt/__init__.py +3 -17
- pyfemtet/opt/exceptions.py +45 -0
- pyfemtet/opt/femopt.py +608 -0
- pyfemtet/opt/history/__init__.py +11 -0
- pyfemtet/opt/history/_history.py +1404 -0
- pyfemtet/opt/history/_hypervolume.py +169 -0
- pyfemtet/opt/history/_optimality.py +79 -0
- pyfemtet/opt/interface/__init__.py +17 -24
- pyfemtet/opt/interface/_base_interface.py +222 -0
- pyfemtet/opt/interface/_excel_interface/__init__.py +3 -0
- pyfemtet/opt/interface/_excel_interface/debug-excel-interface.xlsm +0 -0
- pyfemtet/opt/interface/_excel_interface/excel_interface.py +999 -0
- pyfemtet/opt/interface/_femtet_interface/__init__.py +3 -0
- pyfemtet/opt/interface/{_femtet_parametric.py → _femtet_interface/_femtet_parametric.py} +20 -12
- pyfemtet/opt/interface/{_femtet.py → _femtet_interface/femtet_interface.py} +505 -349
- pyfemtet/opt/interface/_femtet_with_nx_interface/__init__.py +5 -0
- pyfemtet/opt/interface/_femtet_with_nx_interface/femtet_with_nx_interface.py +230 -0
- pyfemtet/opt/interface/_femtet_with_nx_interface/model1.prt +0 -0
- pyfemtet/opt/interface/_femtet_with_nx_interface/model1.x_t +98 -0
- pyfemtet/opt/interface/{_femtet_with_nx → _femtet_with_nx_interface}/update_model.py +1 -3
- pyfemtet/opt/interface/_femtet_with_solidworks/__init__.py +5 -0
- pyfemtet/opt/interface/_femtet_with_solidworks/femtet_with_solidworks_interface.py +122 -0
- pyfemtet/opt/interface/_solidworks_interface/__init__.py +5 -0
- pyfemtet/opt/interface/_solidworks_interface/solidworks_interface.py +206 -0
- pyfemtet/opt/interface/_surrogate_model_interface/__init__.py +8 -0
- pyfemtet/opt/interface/_surrogate_model_interface/base_surrogate_interface.py +150 -0
- pyfemtet/opt/interface/_surrogate_model_interface/botorch_interface.py +298 -0
- pyfemtet/opt/interface/_surrogate_model_interface/debug-pof-botorch.reccsv +18 -0
- pyfemtet/opt/interface/_with_excel_settings/__init__.py +61 -0
- pyfemtet/opt/interface/_with_excel_settings/with_excel_settings.py +134 -0
- pyfemtet/opt/meta_script/YAML_Generator.xlsm +0 -0
- pyfemtet/opt/meta_script/__main__.py +58 -36
- pyfemtet/opt/optimizer/__init__.py +7 -9
- pyfemtet/opt/optimizer/_base_optimizer.py +885 -0
- pyfemtet/opt/optimizer/optuna_optimizer/__init__.py +9 -0
- pyfemtet/opt/optimizer/optuna_optimizer/_optuna_attribute.py +73 -0
- pyfemtet/opt/optimizer/optuna_optimizer/_optuna_optimizer.py +678 -0
- pyfemtet/opt/optimizer/optuna_optimizer/_pof_botorch/__init__.py +7 -0
- pyfemtet/opt/optimizer/optuna_optimizer/_pof_botorch/debug-pof-botorch.reccsv +18 -0
- pyfemtet/opt/optimizer/optuna_optimizer/_pof_botorch/enable_nonlinear_constraint.py +244 -0
- pyfemtet/opt/optimizer/optuna_optimizer/_pof_botorch/pof_botorch_sampler.py +1249 -0
- pyfemtet/opt/optimizer/optuna_optimizer/wat_ex14_parametric_jp.femprj +0 -0
- pyfemtet/opt/optimizer/scipy_optimizer/__init__.py +1 -0
- pyfemtet/opt/optimizer/scipy_optimizer/_scipy_optimizer.py +364 -0
- pyfemtet/opt/prediction/__init__.py +7 -0
- pyfemtet/opt/prediction/_botorch_utils.py +133 -0
- pyfemtet/opt/prediction/_gpytorch_modules_extension.py +142 -0
- pyfemtet/opt/prediction/_helper.py +155 -0
- pyfemtet/opt/prediction/_model.py +118 -0
- pyfemtet/opt/problem/problem.py +304 -0
- pyfemtet/opt/problem/variable_manager/__init__.py +20 -0
- pyfemtet/opt/problem/variable_manager/_string_as_expression.py +115 -0
- pyfemtet/opt/problem/variable_manager/_variable_manager.py +295 -0
- pyfemtet/opt/visualization/history_viewer/__main__.py +5 -0
- pyfemtet/opt/visualization/{_base.py → history_viewer/_base_application.py} +18 -13
- pyfemtet/opt/visualization/history_viewer/_common_pages.py +150 -0
- pyfemtet/opt/visualization/{_complex_components → history_viewer/_complex_components}/alert_region.py +10 -5
- pyfemtet/opt/visualization/{_complex_components → history_viewer/_complex_components}/control_femtet.py +16 -13
- pyfemtet/opt/visualization/{_complex_components → history_viewer/_complex_components}/main_graph.py +117 -47
- pyfemtet/opt/visualization/{_complex_components → history_viewer/_complex_components}/pm_graph.py +159 -138
- pyfemtet/opt/visualization/history_viewer/_process_monitor/_application.py +173 -0
- pyfemtet/opt/visualization/history_viewer/_process_monitor/_pages.py +291 -0
- pyfemtet/opt/visualization/{_wrapped_components → history_viewer/_wrapped_components}/dbc.py +1 -1
- pyfemtet/opt/visualization/{_wrapped_components → history_viewer/_wrapped_components}/dcc.py +1 -1
- pyfemtet/opt/visualization/{_wrapped_components → history_viewer/_wrapped_components}/html.py +1 -1
- pyfemtet/opt/visualization/history_viewer/result_viewer/__main__.py +5 -0
- pyfemtet/opt/visualization/{result_viewer/application.py → history_viewer/result_viewer/_application.py} +6 -6
- pyfemtet/opt/visualization/{result_viewer/pages.py → history_viewer/result_viewer/_pages.py} +106 -82
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08.csv +18 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08.db +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8.jpg +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8.log +45 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8.pdt +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_1.jpg +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_1.pdt +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_10.jpg +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_10.pdt +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_11.jpg +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_11.pdt +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_12.jpg +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_12.pdt +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_13.jpg +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_13.pdt +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_14.jpg +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_14.pdt +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_15.jpg +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_15.pdt +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_16.jpg +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_16.pdt +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_17.jpg +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_17.pdt +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_18.jpg +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_18.pdt +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_19.jpg +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_19.pdt +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_2.jpg +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_2.pdt +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_20.jpg +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_20.pdt +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_3.jpg +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_3.pdt +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_4.bgr +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_4.bnd +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_4.btr +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_4.jpg +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_4.mtl +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_4.pdt +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_4.prm +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_5.jpg +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_5.pdt +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_6.jpg +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_6.pdt +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_7.jpg +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_7.pdt +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_8.jpg +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_8.pdt +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_9.jpg +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_9.pdt +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.femprj +0 -0
- pyfemtet/opt/visualization/plotter/main_figure_creator.py +536 -0
- pyfemtet/opt/visualization/plotter/pm_graph_creator.py +359 -0
- pyfemtet/opt/worker_status.py +120 -0
- {pyfemtet-0.9.5.dist-info → pyfemtet-1.0.0b0.dist-info}/METADATA +23 -24
- pyfemtet-1.0.0b0.dist-info/RECORD +172 -0
- pyfemtet-1.0.0b0.dist-info/entry_points.txt +3 -0
- pyfemtet/_femtet_config_util/exit.py +0 -59
- pyfemtet/_message/1. make_pot.bat +0 -11
- pyfemtet/_message/2. make_mo.bat +0 -6
- pyfemtet/_message/__init__.py +0 -5
- pyfemtet/_message/babel.cfg +0 -2
- pyfemtet/_message/locales/ja/LC_MESSAGES/messages.mo +0 -0
- pyfemtet/_message/locales/ja/LC_MESSAGES/messages.po +0 -570
- pyfemtet/_message/locales/messages.pot +0 -551
- pyfemtet/_warning.py +0 -87
- pyfemtet/brep/_impl.py +0 -18
- pyfemtet/opt/_femopt.py +0 -1007
- pyfemtet/opt/_femopt_core.py +0 -1169
- pyfemtet/opt/_test_utils/control_femtet.py +0 -39
- pyfemtet/opt/_test_utils/hyper_sphere.py +0 -24
- pyfemtet/opt/_test_utils/record_history.py +0 -130
- pyfemtet/opt/advanced_samples/excel_ui/(ref) original_project.femprj +0 -0
- pyfemtet/opt/advanced_samples/excel_ui/femtet-macro.xlsm +0 -0
- pyfemtet/opt/advanced_samples/excel_ui/pyfemtet-core.py +0 -291
- pyfemtet/opt/advanced_samples/excel_ui/test-pyfemtet-core.cmd +0 -22
- pyfemtet/opt/advanced_samples/restart/gal_ex13_parametric.femprj +0 -0
- pyfemtet/opt/advanced_samples/restart/gal_ex13_parametric_restart.py +0 -99
- pyfemtet/opt/advanced_samples/restart/gal_ex13_parametric_restart_jp.py +0 -102
- pyfemtet/opt/advanced_samples/surrogate_model/gal_ex13_create_training_data.py +0 -60
- pyfemtet/opt/advanced_samples/surrogate_model/gal_ex13_create_training_data_jp.py +0 -57
- pyfemtet/opt/advanced_samples/surrogate_model/gal_ex13_optimize_with_surrogate.py +0 -100
- pyfemtet/opt/advanced_samples/surrogate_model/gal_ex13_optimize_with_surrogate_jp.py +0 -90
- pyfemtet/opt/advanced_samples/surrogate_model/gal_ex13_parametric.femprj +0 -0
- pyfemtet/opt/interface/_base.py +0 -101
- pyfemtet/opt/interface/_excel_interface.py +0 -984
- pyfemtet/opt/interface/_femtet_excel.py +0 -141
- pyfemtet/opt/interface/_femtet_with_nx/__init__.py +0 -3
- pyfemtet/opt/interface/_femtet_with_nx/_interface.py +0 -178
- pyfemtet/opt/interface/_femtet_with_sldworks.py +0 -298
- pyfemtet/opt/interface/_surrogate/__init__.py +0 -5
- pyfemtet/opt/interface/_surrogate/_base.py +0 -129
- pyfemtet/opt/interface/_surrogate/_chaospy.py +0 -71
- pyfemtet/opt/interface/_surrogate/_singletaskgp.py +0 -71
- pyfemtet/opt/interface/_surrogate_excel.py +0 -102
- pyfemtet/opt/optimizer/_base.py +0 -376
- pyfemtet/opt/optimizer/_optuna/_botorch_patch/enable_nonlinear_constraint.py +0 -220
- pyfemtet/opt/optimizer/_optuna/_optuna.py +0 -434
- pyfemtet/opt/optimizer/_optuna/_pof_botorch.py +0 -1914
- pyfemtet/opt/optimizer/_scipy.py +0 -159
- pyfemtet/opt/optimizer/_scipy_scalar.py +0 -127
- pyfemtet/opt/optimizer/parameter.py +0 -113
- pyfemtet/opt/prediction/_base.py +0 -61
- pyfemtet/opt/prediction/single_task_gp.py +0 -119
- pyfemtet/opt/samples/femprj_sample/ParametricIF.femprj +0 -0
- pyfemtet/opt/samples/femprj_sample/ParametricIF.py +0 -29
- pyfemtet/opt/samples/femprj_sample/ParametricIF_test_result.reccsv +0 -13
- pyfemtet/opt/samples/femprj_sample/cad_ex01_NX.femprj +0 -0
- pyfemtet/opt/samples/femprj_sample/cad_ex01_NX.prt +0 -0
- pyfemtet/opt/samples/femprj_sample/cad_ex01_NX.py +0 -135
- pyfemtet/opt/samples/femprj_sample/cad_ex01_NX_test_result.reccsv +0 -23
- pyfemtet/opt/samples/femprj_sample/cad_ex01_SW.SLDPRT +0 -0
- pyfemtet/opt/samples/femprj_sample/cad_ex01_SW.femprj +0 -0
- pyfemtet/opt/samples/femprj_sample/cad_ex01_SW.py +0 -131
- pyfemtet/opt/samples/femprj_sample/cad_ex01_SW_test_result.reccsv +0 -23
- pyfemtet/opt/samples/femprj_sample/constrained_pipe.femprj +0 -0
- pyfemtet/opt/samples/femprj_sample/constrained_pipe.py +0 -96
- pyfemtet/opt/samples/femprj_sample/constrained_pipe_test_result.reccsv +0 -13
- pyfemtet/opt/samples/femprj_sample/gal_ex58_parametric.femprj +0 -0
- pyfemtet/opt/samples/femprj_sample/gal_ex58_parametric.py +0 -74
- pyfemtet/opt/samples/femprj_sample/gal_ex58_parametric_test_result.reccsv +0 -13
- pyfemtet/opt/samples/femprj_sample/gau_ex08_parametric.femprj +0 -0
- pyfemtet/opt/samples/femprj_sample/gau_ex08_parametric.py +0 -58
- pyfemtet/opt/samples/femprj_sample/gau_ex08_parametric_test_result.reccsv +0 -23
- pyfemtet/opt/samples/femprj_sample/gau_ex12_parametric.femprj +0 -0
- pyfemtet/opt/samples/femprj_sample/gau_ex12_parametric.py +0 -52
- pyfemtet/opt/samples/femprj_sample/her_ex40_parametric.femprj +0 -0
- pyfemtet/opt/samples/femprj_sample/her_ex40_parametric.py +0 -138
- pyfemtet/opt/samples/femprj_sample/her_ex40_parametric_test_result.reccsv +0 -18
- pyfemtet/opt/samples/femprj_sample/paswat_ex1_parametric.femprj +0 -0
- pyfemtet/opt/samples/femprj_sample/paswat_ex1_parametric.py +0 -60
- pyfemtet/opt/samples/femprj_sample/paswat_ex1_parametric_parallel.py +0 -61
- pyfemtet/opt/samples/femprj_sample/paswat_ex1_parametric_test_result.reccsv +0 -18
- pyfemtet/opt/samples/femprj_sample/wat_ex14_parametric.femprj +0 -0
- pyfemtet/opt/samples/femprj_sample/wat_ex14_parametric.py +0 -58
- pyfemtet/opt/samples/femprj_sample/wat_ex14_parametric_parallel.py +0 -58
- pyfemtet/opt/samples/femprj_sample/wat_ex14_parametric_test_result.reccsv +0 -18
- pyfemtet/opt/samples/femprj_sample_jp/ParametricIF_jp.femprj +0 -0
- pyfemtet/opt/samples/femprj_sample_jp/ParametricIF_jp.py +0 -29
- pyfemtet/opt/samples/femprj_sample_jp/cad_ex01_NX_jp.femprj +0 -0
- pyfemtet/opt/samples/femprj_sample_jp/cad_ex01_NX_jp.py +0 -129
- pyfemtet/opt/samples/femprj_sample_jp/cad_ex01_SW_jp.femprj +0 -0
- pyfemtet/opt/samples/femprj_sample_jp/cad_ex01_SW_jp.py +0 -125
- pyfemtet/opt/samples/femprj_sample_jp/constrained_pipe_jp.py +0 -93
- pyfemtet/opt/samples/femprj_sample_jp/gal_ex58_parametric_jp.femprj +0 -0
- pyfemtet/opt/samples/femprj_sample_jp/gal_ex58_parametric_jp.py +0 -70
- pyfemtet/opt/samples/femprj_sample_jp/gau_ex08_parametric_jp.femprj +0 -0
- pyfemtet/opt/samples/femprj_sample_jp/gau_ex08_parametric_jp.py +0 -57
- pyfemtet/opt/samples/femprj_sample_jp/gau_ex12_parametric_jp.py +0 -52
- pyfemtet/opt/samples/femprj_sample_jp/her_ex40_parametric_jp.femprj +0 -0
- pyfemtet/opt/samples/femprj_sample_jp/her_ex40_parametric_jp.py +0 -138
- pyfemtet/opt/samples/femprj_sample_jp/paswat_ex1_parametric_jp.femprj +0 -0
- pyfemtet/opt/samples/femprj_sample_jp/paswat_ex1_parametric_jp.py +0 -58
- pyfemtet/opt/samples/femprj_sample_jp/paswat_ex1_parametric_parallel_jp.py +0 -59
- pyfemtet/opt/samples/femprj_sample_jp/wat_ex14_parametric_jp.py +0 -56
- pyfemtet/opt/samples/femprj_sample_jp/wat_ex14_parametric_parallel_jp.py +0 -56
- pyfemtet/opt/visualization/_complex_components/main_figure_creator.py +0 -332
- pyfemtet/opt/visualization/_complex_components/pm_graph_creator.py +0 -201
- pyfemtet/opt/visualization/_process_monitor/application.py +0 -226
- pyfemtet/opt/visualization/_process_monitor/pages.py +0 -406
- pyfemtet/opt/visualization/_wrapped_components/__init__.py +0 -0
- pyfemtet/opt/visualization/result_viewer/__init__.py +0 -0
- pyfemtet-0.9.5.dist-info/RECORD +0 -158
- pyfemtet-0.9.5.dist-info/entry_points.txt +0 -3
- /pyfemtet/{_femtet_config_util → opt/problem}/__init__.py +0 -0
- /pyfemtet/{brep → opt/visualization/history_viewer}/__init__.py +0 -0
- /pyfemtet/opt/{_test_utils → visualization/history_viewer/_complex_components}/__init__.py +0 -0
- /pyfemtet/opt/{optimizer/_optuna → visualization/history_viewer/_process_monitor}/__init__.py +0 -0
- /pyfemtet/opt/{optimizer/_optuna/_botorch_patch → visualization/history_viewer/_wrapped_components}/__init__.py +0 -0
- /pyfemtet/opt/visualization/{_wrapped_components → history_viewer/_wrapped_components}/str_enum.py +0 -0
- /pyfemtet/opt/visualization/{result_viewer → history_viewer/result_viewer}/.gitignore +0 -0
- /pyfemtet/opt/visualization/{_complex_components → history_viewer/result_viewer}/__init__.py +0 -0
- /pyfemtet/opt/visualization/{_process_monitor → plotter}/__init__.py +0 -0
- /pyfemtet/opt/{samples/femprj_sample_jp/wat_ex14_parametric_jp.femprj → wat_ex14_parametric_jp.femprj} +0 -0
- {pyfemtet-0.9.5.dist-info → pyfemtet-1.0.0b0.dist-info}/LICENSE +0 -0
- {pyfemtet-0.9.5.dist-info → pyfemtet-1.0.0b0.dist-info}/LICENSE_THIRD_PARTY.txt +0 -0
- {pyfemtet-0.9.5.dist-info → pyfemtet-1.0.0b0.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,885 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import datetime
|
|
4
|
+
from typing import Callable, TypeAlias, Sequence, Literal
|
|
5
|
+
from numbers import Real # マイナーなので型ヒントでは使わず、isinstance で使う
|
|
6
|
+
from time import sleep
|
|
7
|
+
|
|
8
|
+
import sympy
|
|
9
|
+
|
|
10
|
+
from pyfemtet._i18n.messages import _
|
|
11
|
+
from pyfemtet.opt.history import *
|
|
12
|
+
from pyfemtet.opt.interface import *
|
|
13
|
+
from pyfemtet.opt.exceptions import *
|
|
14
|
+
from pyfemtet.opt.worker_status import *
|
|
15
|
+
from pyfemtet.opt.problem.problem import *
|
|
16
|
+
from pyfemtet.opt.problem.variable_manager import *
|
|
17
|
+
from pyfemtet.logger import get_module_logger
|
|
18
|
+
|
|
19
|
+
__all__ = [
|
|
20
|
+
'AbstractOptimizer',
|
|
21
|
+
'SubFidelityModel',
|
|
22
|
+
'SubFidelityModels',
|
|
23
|
+
'_FReturnValue',
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
DIRECTION: TypeAlias = (
|
|
28
|
+
float
|
|
29
|
+
| Literal[
|
|
30
|
+
'minimize',
|
|
31
|
+
'maximize',
|
|
32
|
+
]
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
logger = get_module_logger('opt.optimizer', False)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _log_hidden_constraint(e: Exception):
|
|
39
|
+
err_msg = create_err_msg_from_exception(e)
|
|
40
|
+
logger.warning(_('----- Hidden constraint violation! -----'))
|
|
41
|
+
logger.warning(_('error: {err_msg}', err_msg=err_msg))
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
_FReturnValue: TypeAlias = tuple[TrialOutput, dict[str, float], TrialConstraintOutput, Record]
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _duplicated_name_check(name, names):
|
|
48
|
+
if name in names:
|
|
49
|
+
logger.warning(
|
|
50
|
+
_(
|
|
51
|
+
en_message='There are duplicated name {name}. If there are '
|
|
52
|
+
'duplicate names for parameters or objective '
|
|
53
|
+
'functions, the later defined ones will overwrite '
|
|
54
|
+
'the earlier ones. Please be careful to ensure '
|
|
55
|
+
'that this overwriting is intentional.',
|
|
56
|
+
jp_message='名前 {name} が重複しています。パラメータや目的関数'
|
|
57
|
+
'などの名前が重複すると、後から定義したものが上書き'
|
|
58
|
+
'されます。この上書きが意図したものであるかどうか、'
|
|
59
|
+
'十分に注意してください。',
|
|
60
|
+
name=name,
|
|
61
|
+
)
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class AbstractOptimizer:
|
|
66
|
+
|
|
67
|
+
# optimize
|
|
68
|
+
n_trials: int | None
|
|
69
|
+
timeout: float | None
|
|
70
|
+
seed: int | None
|
|
71
|
+
|
|
72
|
+
# problem
|
|
73
|
+
variable_manager: VariableManager
|
|
74
|
+
objectives: Objectives
|
|
75
|
+
constraints: Constraints
|
|
76
|
+
fidelity: Fidelity | None
|
|
77
|
+
sub_fidelity_name: str
|
|
78
|
+
sub_fidelity_models: SubFidelityModels | None
|
|
79
|
+
|
|
80
|
+
# system
|
|
81
|
+
history: History
|
|
82
|
+
fem: AbstractFEMInterface
|
|
83
|
+
entire_status: WorkerStatus
|
|
84
|
+
worker_status: WorkerStatus
|
|
85
|
+
worker_status_list: list[WorkerStatus]
|
|
86
|
+
_done_setup_before_parallel: bool
|
|
87
|
+
_done_load_problem_from_fem: bool
|
|
88
|
+
_worker_index: int | str | None
|
|
89
|
+
_worker_name: str | None
|
|
90
|
+
|
|
91
|
+
def __init__(self):
|
|
92
|
+
|
|
93
|
+
# optimization
|
|
94
|
+
self.seed = None
|
|
95
|
+
self.n_trials = None
|
|
96
|
+
self.timeout = None
|
|
97
|
+
|
|
98
|
+
# Problem
|
|
99
|
+
self.variable_manager = VariableManager()
|
|
100
|
+
self.objectives = Objectives()
|
|
101
|
+
self.constraints = Constraints()
|
|
102
|
+
|
|
103
|
+
# multi-fidelity
|
|
104
|
+
self.fidelity = None
|
|
105
|
+
self.sub_fidelity_name = MAIN_FIDELITY_NAME
|
|
106
|
+
self.sub_fidelity_models = SubFidelityModels()
|
|
107
|
+
|
|
108
|
+
# System
|
|
109
|
+
self.fem: AbstractFEMInterface | None = None
|
|
110
|
+
self.history: History = History()
|
|
111
|
+
self.solve_condition: Callable[[History], bool] = lambda _: True
|
|
112
|
+
self.entire_status: WorkerStatus = WorkerStatus(ENTIRE_PROCESS_STATUS_KEY)
|
|
113
|
+
self.worker_status: WorkerStatus = WorkerStatus('worker-status')
|
|
114
|
+
self.worker_status_list: list[WorkerStatus] = [self.worker_status]
|
|
115
|
+
self._done_setup_before_parallel = False
|
|
116
|
+
self._done_load_problem_from_fem = False
|
|
117
|
+
self._worker_index: int | str | None = None
|
|
118
|
+
self._worker_name: str | None = None
|
|
119
|
+
|
|
120
|
+
# ===== public =====
|
|
121
|
+
|
|
122
|
+
def add_constant_value(
|
|
123
|
+
self,
|
|
124
|
+
name: str,
|
|
125
|
+
value: SupportedVariableTypes,
|
|
126
|
+
properties: dict[str, ...] | None = None,
|
|
127
|
+
*,
|
|
128
|
+
pass_to_fem: bool = True,
|
|
129
|
+
):
|
|
130
|
+
if isinstance(value, Real):
|
|
131
|
+
var = NumericVariable()
|
|
132
|
+
elif isinstance(value, str):
|
|
133
|
+
var = CategoricalVariable()
|
|
134
|
+
else:
|
|
135
|
+
raise ValueError(_(
|
|
136
|
+
en_message='Supported variable types are Real or str, got {type}',
|
|
137
|
+
jp_message='サポートされている変数の型は Real か str ですが、{type} が指定されました。',
|
|
138
|
+
type=type(value),
|
|
139
|
+
))
|
|
140
|
+
var.name = name
|
|
141
|
+
var.value = value
|
|
142
|
+
var.pass_to_fem = pass_to_fem
|
|
143
|
+
var.properties = properties if properties is not None else {}
|
|
144
|
+
_duplicated_name_check(name, self.variable_manager.variables.keys())
|
|
145
|
+
self.variable_manager.variables.update({name: var})
|
|
146
|
+
|
|
147
|
+
def add_parameter(
|
|
148
|
+
self,
|
|
149
|
+
name: str,
|
|
150
|
+
initial_value: float | None = None,
|
|
151
|
+
lower_bound: float | None = None,
|
|
152
|
+
upper_bound: float | None = None,
|
|
153
|
+
step: float | None = None,
|
|
154
|
+
properties: dict[str, ...] | None = None,
|
|
155
|
+
*,
|
|
156
|
+
pass_to_fem: bool = True,
|
|
157
|
+
fix: bool = False,
|
|
158
|
+
) -> None:
|
|
159
|
+
properties = properties if properties is not None else {}
|
|
160
|
+
|
|
161
|
+
if fix:
|
|
162
|
+
properties.update({'fix': True})
|
|
163
|
+
|
|
164
|
+
prm = NumericParameter()
|
|
165
|
+
prm.name = name
|
|
166
|
+
prm.value = initial_value
|
|
167
|
+
prm.lower_bound = lower_bound
|
|
168
|
+
prm.upper_bound = upper_bound
|
|
169
|
+
prm.step = step
|
|
170
|
+
prm.properties = properties
|
|
171
|
+
prm.pass_to_fem = pass_to_fem
|
|
172
|
+
_duplicated_name_check(name, self.variable_manager.variables.keys())
|
|
173
|
+
self.variable_manager.variables.update({name: prm})
|
|
174
|
+
|
|
175
|
+
def add_expression_string(
|
|
176
|
+
self,
|
|
177
|
+
name: str,
|
|
178
|
+
expression_string: str,
|
|
179
|
+
properties: dict[str, ...] | None = None,
|
|
180
|
+
*,
|
|
181
|
+
pass_to_fem: bool = True,
|
|
182
|
+
) -> None:
|
|
183
|
+
var = ExpressionFromString()
|
|
184
|
+
var.name = name
|
|
185
|
+
var._expr = ExpressionFromString.InternalClass(expression_string=expression_string)
|
|
186
|
+
var.properties = properties or dict()
|
|
187
|
+
var.pass_to_fem = pass_to_fem
|
|
188
|
+
_duplicated_name_check(name, self.variable_manager.variables.keys())
|
|
189
|
+
self.variable_manager.variables.update({name: var})
|
|
190
|
+
|
|
191
|
+
def add_expression_sympy(
|
|
192
|
+
self,
|
|
193
|
+
name: str,
|
|
194
|
+
sympy_expr: sympy.Expr,
|
|
195
|
+
properties: dict[str, ...] | None = None,
|
|
196
|
+
*,
|
|
197
|
+
pass_to_fem: bool = True,
|
|
198
|
+
) -> None:
|
|
199
|
+
var = ExpressionFromString()
|
|
200
|
+
var.name = name
|
|
201
|
+
var._expr = ExpressionFromString.InternalClass(sympy_expr=sympy_expr)
|
|
202
|
+
var.properties = properties or dict()
|
|
203
|
+
var.pass_to_fem = pass_to_fem
|
|
204
|
+
_duplicated_name_check(name, self.variable_manager.variables.keys())
|
|
205
|
+
self.variable_manager.variables.update({name: var})
|
|
206
|
+
|
|
207
|
+
def add_expression(
|
|
208
|
+
self,
|
|
209
|
+
name: str,
|
|
210
|
+
fun: Callable[..., float],
|
|
211
|
+
properties: dict[str, ...] | None = None,
|
|
212
|
+
args: tuple | None = None,
|
|
213
|
+
kwargs: dict | None = None,
|
|
214
|
+
*,
|
|
215
|
+
pass_to_fem: bool = True,
|
|
216
|
+
) -> None:
|
|
217
|
+
var = ExpressionFromFunction()
|
|
218
|
+
var.name = name
|
|
219
|
+
var.fun = fun
|
|
220
|
+
var.args = args or tuple()
|
|
221
|
+
var.kwargs = kwargs or dict()
|
|
222
|
+
var.properties = properties or dict()
|
|
223
|
+
var.pass_to_fem = pass_to_fem
|
|
224
|
+
_duplicated_name_check(name, self.variable_manager.variables.keys())
|
|
225
|
+
self.variable_manager.variables.update({name: var})
|
|
226
|
+
|
|
227
|
+
def add_categorical_parameter(
|
|
228
|
+
self,
|
|
229
|
+
name: str,
|
|
230
|
+
initial_value: str | None = None,
|
|
231
|
+
choices: list[str] | None = None,
|
|
232
|
+
properties: dict[str, ...] | None = None,
|
|
233
|
+
*,
|
|
234
|
+
pass_to_fem: bool = True,
|
|
235
|
+
fix: bool = False,
|
|
236
|
+
) -> None:
|
|
237
|
+
properties = properties if properties is not None else {}
|
|
238
|
+
|
|
239
|
+
if fix:
|
|
240
|
+
properties.update({'fix': True})
|
|
241
|
+
|
|
242
|
+
prm = CategoricalParameter()
|
|
243
|
+
prm.name = name
|
|
244
|
+
prm.value = initial_value
|
|
245
|
+
prm.choices = choices
|
|
246
|
+
prm.properties = properties
|
|
247
|
+
prm.pass_to_fem = pass_to_fem
|
|
248
|
+
_duplicated_name_check(name, self.variable_manager.variables.keys())
|
|
249
|
+
self.variable_manager.variables.update({name: prm})
|
|
250
|
+
|
|
251
|
+
def add_objective(
|
|
252
|
+
self,
|
|
253
|
+
name: str,
|
|
254
|
+
fun: Callable[..., float],
|
|
255
|
+
direction: DIRECTION = 'minimize',
|
|
256
|
+
args: tuple | None = None,
|
|
257
|
+
kwargs: dict | None = None,
|
|
258
|
+
) -> None:
|
|
259
|
+
obj = Objective()
|
|
260
|
+
obj.fun = fun
|
|
261
|
+
obj.args = args or ()
|
|
262
|
+
obj.kwargs = kwargs or {}
|
|
263
|
+
obj.direction = direction
|
|
264
|
+
_duplicated_name_check(name, self.objectives.keys())
|
|
265
|
+
self.objectives.update({name: obj})
|
|
266
|
+
|
|
267
|
+
def add_objectives(
|
|
268
|
+
self,
|
|
269
|
+
names: str | list[str],
|
|
270
|
+
fun: Callable[..., Sequence[float]],
|
|
271
|
+
n_return: int,
|
|
272
|
+
directions: DIRECTION | Sequence[DIRECTION | None] | None = None,
|
|
273
|
+
args: tuple | None = None,
|
|
274
|
+
kwargs: dict | None = None,
|
|
275
|
+
):
|
|
276
|
+
# argument processing
|
|
277
|
+
if isinstance(names, str):
|
|
278
|
+
names = [f'{names}_{i}' for i in range(n_return)]
|
|
279
|
+
elif isinstance(names, Sequence):
|
|
280
|
+
# names = names
|
|
281
|
+
pass
|
|
282
|
+
else:
|
|
283
|
+
raise ValueError(
|
|
284
|
+
_(en_message='`names` must be a string or an array of strings.',
|
|
285
|
+
jp_message='`names` は文字列か文字列の配列でなければなりません。',)
|
|
286
|
+
)
|
|
287
|
+
|
|
288
|
+
if directions is None:
|
|
289
|
+
directions = ['minimize' for __ in range(n_return)]
|
|
290
|
+
else:
|
|
291
|
+
if isinstance(directions, str) or isinstance(directions, Real):
|
|
292
|
+
directions = [directions for __ in range(n_return)]
|
|
293
|
+
else:
|
|
294
|
+
# directions = directions
|
|
295
|
+
pass
|
|
296
|
+
|
|
297
|
+
assert len(names) == len(directions) == n_return
|
|
298
|
+
|
|
299
|
+
function_factory = ObjectivesFunc(fun, n_return)
|
|
300
|
+
for i, (name, direction) in enumerate(zip(names, directions)):
|
|
301
|
+
fun_i = function_factory.get_fun_that_returns_ith_value(i)
|
|
302
|
+
self.add_objective(
|
|
303
|
+
fun=fun_i,
|
|
304
|
+
name=name,
|
|
305
|
+
direction=direction,
|
|
306
|
+
args=args,
|
|
307
|
+
kwargs=kwargs,
|
|
308
|
+
)
|
|
309
|
+
|
|
310
|
+
def add_constraint(
|
|
311
|
+
self,
|
|
312
|
+
name: str,
|
|
313
|
+
fun: Callable[..., float],
|
|
314
|
+
lower_bound: float | None = None,
|
|
315
|
+
upper_bound: float | None = None,
|
|
316
|
+
args: tuple | None = None,
|
|
317
|
+
kwargs: dict | None = None,
|
|
318
|
+
strict: bool = True,
|
|
319
|
+
using_fem: bool | None = None,
|
|
320
|
+
):
|
|
321
|
+
|
|
322
|
+
if lower_bound is None and upper_bound is None:
|
|
323
|
+
raise ValueError(_(
|
|
324
|
+
en_message='One of `lower_bound` and `upper_bound` '
|
|
325
|
+
'should be set.',
|
|
326
|
+
jp_message='`lower_bound` and `upper_bound` のうち'
|
|
327
|
+
'少なくとも一つは指定されなければなりません。'
|
|
328
|
+
))
|
|
329
|
+
|
|
330
|
+
cns = Constraint()
|
|
331
|
+
cns.fun = fun
|
|
332
|
+
cns.args = args or ()
|
|
333
|
+
cns.kwargs = kwargs or {}
|
|
334
|
+
cns.lower_bound = lower_bound
|
|
335
|
+
cns.upper_bound = upper_bound
|
|
336
|
+
cns.hard = strict
|
|
337
|
+
cns._opt = self
|
|
338
|
+
cns.using_fem = using_fem
|
|
339
|
+
_duplicated_name_check(name, self.constraints.keys())
|
|
340
|
+
self.constraints.update({name: cns})
|
|
341
|
+
|
|
342
|
+
def add_sub_fidelity_model(
|
|
343
|
+
self,
|
|
344
|
+
name: str,
|
|
345
|
+
sub_fidelity_model: SubFidelityModel,
|
|
346
|
+
fidelity: Fidelity,
|
|
347
|
+
):
|
|
348
|
+
sub_fidelity_model.variable_manager = self.variable_manager
|
|
349
|
+
if self.sub_fidelity_models is None:
|
|
350
|
+
self.sub_fidelity_models = SubFidelityModels()
|
|
351
|
+
self.fidelity = 1.
|
|
352
|
+
_duplicated_name_check(name, self.sub_fidelity_models.keys())
|
|
353
|
+
self.sub_fidelity_models._update(name, sub_fidelity_model, fidelity)
|
|
354
|
+
|
|
355
|
+
def get_variables(self, format='dict'):
|
|
356
|
+
return self.variable_manager.get_variables(
|
|
357
|
+
format=format,
|
|
358
|
+
)
|
|
359
|
+
|
|
360
|
+
def get_parameter(self, format='dict'):
|
|
361
|
+
return self.variable_manager.get_variables(
|
|
362
|
+
format=format, filter='parameter'
|
|
363
|
+
)
|
|
364
|
+
|
|
365
|
+
def set_solve_condition(self, fun: Callable[[History], bool]):
|
|
366
|
+
self.solve_condition = fun
|
|
367
|
+
|
|
368
|
+
# ===== private =====
|
|
369
|
+
|
|
370
|
+
def _should_solve(self, history):
|
|
371
|
+
return self.solve_condition(history)
|
|
372
|
+
|
|
373
|
+
def _y(self) -> TrialOutput:
|
|
374
|
+
out = TrialOutput()
|
|
375
|
+
for name, obj in self.objectives.items():
|
|
376
|
+
obj_result = ObjectiveResult(obj, self.fem)
|
|
377
|
+
out.update({name: obj_result})
|
|
378
|
+
return out
|
|
379
|
+
|
|
380
|
+
def _convert_y(self, y: TrialOutput) -> dict:
|
|
381
|
+
out = dict()
|
|
382
|
+
for name, result in y.items():
|
|
383
|
+
obj = self.objectives[name]
|
|
384
|
+
value_internal = obj.convert(result.value)
|
|
385
|
+
out.update({name: value_internal})
|
|
386
|
+
return out
|
|
387
|
+
|
|
388
|
+
def _hard_c(self, out: TrialConstraintOutput) -> TrialConstraintOutput:
|
|
389
|
+
for name, cns in self.constraints.items():
|
|
390
|
+
if cns.hard:
|
|
391
|
+
cns_result = ConstraintResult(cns, self.fem)
|
|
392
|
+
out.update({name: cns_result})
|
|
393
|
+
return out
|
|
394
|
+
|
|
395
|
+
def _soft_c(self, out: TrialConstraintOutput) -> TrialConstraintOutput:
|
|
396
|
+
for name, cns in self.constraints.items():
|
|
397
|
+
if not cns.hard:
|
|
398
|
+
cns_result = ConstraintResult(cns, self.fem)
|
|
399
|
+
out.update({name: cns_result})
|
|
400
|
+
return out
|
|
401
|
+
|
|
402
|
+
def _get_hard_constraint_violation_names(self, hard_c: TrialConstraintOutput) -> list[str]:
|
|
403
|
+
violation_names = []
|
|
404
|
+
for name, result in hard_c.items():
|
|
405
|
+
cns = self.constraints[name]
|
|
406
|
+
l_or_u = result.check_violation()
|
|
407
|
+
if l_or_u is not None:
|
|
408
|
+
logger.warning(_('----- Hard constraint violation! -----'))
|
|
409
|
+
logger.warning(_('constraint: {name}', name=name))
|
|
410
|
+
logger.warning(_('evaluated value: {value}', value=result.value))
|
|
411
|
+
if l_or_u == 'lower_bound':
|
|
412
|
+
logger.info(_('lower bound: {lb}', lb=cns.lower_bound))
|
|
413
|
+
violation_names.append(name + '_' + l_or_u)
|
|
414
|
+
elif l_or_u == 'upper_bound':
|
|
415
|
+
logger.info(_('upper bound: {ub}', ub=cns.upper_bound))
|
|
416
|
+
violation_names.append(name + '_' + l_or_u)
|
|
417
|
+
else:
|
|
418
|
+
raise NotImplementedError
|
|
419
|
+
return violation_names
|
|
420
|
+
|
|
421
|
+
def _check_and_raise_interruption(self) -> ...:
|
|
422
|
+
# raise Interrupt
|
|
423
|
+
interrupted = self.entire_status.value >= WorkerStatus.interrupting
|
|
424
|
+
if interrupted:
|
|
425
|
+
self.worker_status.value = WorkerStatus.interrupting
|
|
426
|
+
raise InterruptOptimization
|
|
427
|
+
|
|
428
|
+
# ===== solve =====
|
|
429
|
+
|
|
430
|
+
class _SolveSet:
|
|
431
|
+
|
|
432
|
+
opt: AbstractOptimizer
|
|
433
|
+
opt_: AbstractOptimizer
|
|
434
|
+
|
|
435
|
+
def __init__(self, opt: AbstractOptimizer):
|
|
436
|
+
self.opt: AbstractOptimizer = opt
|
|
437
|
+
|
|
438
|
+
def _preprocess(self):
|
|
439
|
+
pass
|
|
440
|
+
|
|
441
|
+
def _hard_constraint_handling(self, e: HardConstraintViolation):
|
|
442
|
+
pass
|
|
443
|
+
|
|
444
|
+
def _hidden_constraint_handling(self, e: _HiddenConstraintViolation):
|
|
445
|
+
pass
|
|
446
|
+
|
|
447
|
+
def _skip_handling(self, e: SkipSolve):
|
|
448
|
+
pass
|
|
449
|
+
|
|
450
|
+
def _if_succeeded(self, f_return: _FReturnValue):
|
|
451
|
+
pass
|
|
452
|
+
|
|
453
|
+
def _postprocess(self):
|
|
454
|
+
pass
|
|
455
|
+
|
|
456
|
+
def _solve_or_raise(
|
|
457
|
+
self,
|
|
458
|
+
opt_: AbstractOptimizer,
|
|
459
|
+
parameters: TrialInput,
|
|
460
|
+
variables_pass_to_fem: dict[str, SupportedVariableTypes],
|
|
461
|
+
history: History = None,
|
|
462
|
+
datetime_start=None,
|
|
463
|
+
) -> _FReturnValue:
|
|
464
|
+
|
|
465
|
+
# create context
|
|
466
|
+
if history is not None:
|
|
467
|
+
record_to_history = history.recording(opt_.fem)
|
|
468
|
+
else:
|
|
469
|
+
class DummyRecordContext:
|
|
470
|
+
def __enter__(self):
|
|
471
|
+
return Record()
|
|
472
|
+
|
|
473
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
474
|
+
pass
|
|
475
|
+
|
|
476
|
+
record_to_history = DummyRecordContext()
|
|
477
|
+
|
|
478
|
+
# processing with recording
|
|
479
|
+
with record_to_history as record:
|
|
480
|
+
|
|
481
|
+
# record common result
|
|
482
|
+
# input
|
|
483
|
+
record.x = parameters
|
|
484
|
+
# output (the value is nan, required for direction recording to graph)
|
|
485
|
+
record.y = TrialOutput(
|
|
486
|
+
{obj_name: ObjectiveResult(obj, opt_.fem, float('nan'))
|
|
487
|
+
for obj_name, obj in opt_.objectives.items()}
|
|
488
|
+
)
|
|
489
|
+
record.sub_fidelity_name = opt_.sub_fidelity_name
|
|
490
|
+
record.fidelity = opt_.fidelity
|
|
491
|
+
record.datetime_start = datetime_start
|
|
492
|
+
if self.opt._worker_name is not None:
|
|
493
|
+
record.messages.append(self.opt._worker_name)
|
|
494
|
+
|
|
495
|
+
# check skip
|
|
496
|
+
if not opt_._should_solve(history):
|
|
497
|
+
record.state = TrialState.skipped
|
|
498
|
+
raise SkipSolve
|
|
499
|
+
|
|
500
|
+
# start solve
|
|
501
|
+
if opt_.sub_fidelity_models != MAIN_FIDELITY_NAME:
|
|
502
|
+
logger.info(_('fidelity: ({name})', name=opt_.sub_fidelity_name))
|
|
503
|
+
logger.info(_('input variables:'))
|
|
504
|
+
logger.info(parameters)
|
|
505
|
+
|
|
506
|
+
# ===== update FEM parameter =====
|
|
507
|
+
logger.info(_('updating variables...'))
|
|
508
|
+
opt_.fem.update_parameter(variables_pass_to_fem)
|
|
509
|
+
opt_._check_and_raise_interruption()
|
|
510
|
+
|
|
511
|
+
# ===== evaluate hard constraint =====
|
|
512
|
+
logger.info(_('evaluating constraint functions...'))
|
|
513
|
+
|
|
514
|
+
hard_c = TrialConstraintOutput()
|
|
515
|
+
try:
|
|
516
|
+
opt_._hard_c(hard_c)
|
|
517
|
+
|
|
518
|
+
except _HiddenConstraintViolation as e:
|
|
519
|
+
_log_hidden_constraint(e)
|
|
520
|
+
record.c = hard_c
|
|
521
|
+
record.state = TrialState.get_corresponding_state_from_exception(e)
|
|
522
|
+
record.messages.append(
|
|
523
|
+
_('Hidden constraint violation '
|
|
524
|
+
'during hard constraint function '
|
|
525
|
+
'evaluation: ')
|
|
526
|
+
+ create_err_msg_from_exception(e)
|
|
527
|
+
)
|
|
528
|
+
|
|
529
|
+
raise e
|
|
530
|
+
|
|
531
|
+
# check hard constraint violation
|
|
532
|
+
violation_names = opt_._get_hard_constraint_violation_names(hard_c)
|
|
533
|
+
if len(violation_names) > 0:
|
|
534
|
+
record.c = hard_c
|
|
535
|
+
record.state = TrialState.hard_constraint_violation
|
|
536
|
+
record.messages.append(
|
|
537
|
+
_('Hard constraint violation: ')
|
|
538
|
+
+ ', '.join(violation_names))
|
|
539
|
+
|
|
540
|
+
raise HardConstraintViolation
|
|
541
|
+
|
|
542
|
+
# ===== update FEM =====
|
|
543
|
+
logger.info(_('Solving FEM...'))
|
|
544
|
+
|
|
545
|
+
try:
|
|
546
|
+
opt_.fem.update()
|
|
547
|
+
opt_._check_and_raise_interruption()
|
|
548
|
+
|
|
549
|
+
# if hidden constraint violation
|
|
550
|
+
except _HiddenConstraintViolation as e:
|
|
551
|
+
|
|
552
|
+
opt_._check_and_raise_interruption()
|
|
553
|
+
|
|
554
|
+
_log_hidden_constraint(e)
|
|
555
|
+
record.c = hard_c
|
|
556
|
+
record.state = TrialState.get_corresponding_state_from_exception(e)
|
|
557
|
+
record.messages.append(
|
|
558
|
+
_('Hidden constraint violation in FEM update: ')
|
|
559
|
+
+ create_err_msg_from_exception(e))
|
|
560
|
+
|
|
561
|
+
raise e
|
|
562
|
+
|
|
563
|
+
# ===== evaluate y =====
|
|
564
|
+
logger.info(_('evaluating objective functions...'))
|
|
565
|
+
|
|
566
|
+
try:
|
|
567
|
+
y: TrialOutput = opt_._y()
|
|
568
|
+
opt_._check_and_raise_interruption()
|
|
569
|
+
|
|
570
|
+
# if intentional error (by user)
|
|
571
|
+
except _HiddenConstraintViolation as e:
|
|
572
|
+
opt_._check_and_raise_interruption()
|
|
573
|
+
|
|
574
|
+
_log_hidden_constraint(e)
|
|
575
|
+
record.c = hard_c
|
|
576
|
+
record.state = TrialState.get_corresponding_state_from_exception(e)
|
|
577
|
+
record.messages.append(
|
|
578
|
+
_('Hidden constraint violation during '
|
|
579
|
+
'objective function evaluation: ')
|
|
580
|
+
+ create_err_msg_from_exception(e))
|
|
581
|
+
|
|
582
|
+
raise e
|
|
583
|
+
|
|
584
|
+
# ===== evaluate soft constraint =====
|
|
585
|
+
logger.info(_('evaluating remaining constraints...'))
|
|
586
|
+
|
|
587
|
+
soft_c = TrialConstraintOutput()
|
|
588
|
+
try:
|
|
589
|
+
opt_._soft_c(soft_c)
|
|
590
|
+
|
|
591
|
+
# if intentional error (by user)
|
|
592
|
+
except _HiddenConstraintViolation as e:
|
|
593
|
+
_log_hidden_constraint(e)
|
|
594
|
+
|
|
595
|
+
_c = {}
|
|
596
|
+
_c.update(soft_c)
|
|
597
|
+
_c.update(hard_c)
|
|
598
|
+
|
|
599
|
+
record.y = y
|
|
600
|
+
record.c = _c
|
|
601
|
+
record.state = TrialState.get_corresponding_state_from_exception(e)
|
|
602
|
+
record.messages.append(
|
|
603
|
+
_('Hidden constraint violation during '
|
|
604
|
+
'soft constraint function evaluation: ')
|
|
605
|
+
+ create_err_msg_from_exception(e))
|
|
606
|
+
|
|
607
|
+
raise e
|
|
608
|
+
|
|
609
|
+
# ===== merge and sort constraints =====
|
|
610
|
+
c = TrialConstraintOutput()
|
|
611
|
+
c.update(soft_c)
|
|
612
|
+
c.update(hard_c)
|
|
613
|
+
|
|
614
|
+
# get values as minimize
|
|
615
|
+
y_internal: dict = opt_._convert_y(y)
|
|
616
|
+
|
|
617
|
+
logger.info(_('output:'))
|
|
618
|
+
logger.info(y)
|
|
619
|
+
record.y = y
|
|
620
|
+
record.c = c
|
|
621
|
+
record.state = TrialState.succeeded
|
|
622
|
+
|
|
623
|
+
opt_._check_and_raise_interruption()
|
|
624
|
+
|
|
625
|
+
return y, y_internal, c, record
|
|
626
|
+
|
|
627
|
+
def solve(
|
|
628
|
+
self,
|
|
629
|
+
x: TrialInput,
|
|
630
|
+
x_pass_to_fem_: dict[str, SupportedVariableTypes],
|
|
631
|
+
opt_: AbstractOptimizer | None = None,
|
|
632
|
+
) -> _FReturnValue | None:
|
|
633
|
+
|
|
634
|
+
vm = self.opt.variable_manager
|
|
635
|
+
|
|
636
|
+
# opt_ はメインの opt 又は sub_fidelity
|
|
637
|
+
opt_ = opt_ or self.opt
|
|
638
|
+
self.opt_ = opt_
|
|
639
|
+
|
|
640
|
+
# check interruption
|
|
641
|
+
self.opt._check_and_raise_interruption()
|
|
642
|
+
|
|
643
|
+
# if opt_ is not self, update variable manager
|
|
644
|
+
opt_.variable_manager = vm
|
|
645
|
+
|
|
646
|
+
# preprocess
|
|
647
|
+
self._preprocess()
|
|
648
|
+
|
|
649
|
+
# declare output
|
|
650
|
+
f_return = None
|
|
651
|
+
|
|
652
|
+
# start solve
|
|
653
|
+
datetime_start = datetime.datetime.now()
|
|
654
|
+
try:
|
|
655
|
+
f_return = self._solve_or_raise(
|
|
656
|
+
opt_, x, x_pass_to_fem_, self.opt.history, datetime_start
|
|
657
|
+
)
|
|
658
|
+
|
|
659
|
+
except HardConstraintViolation as e:
|
|
660
|
+
self._hard_constraint_handling(e)
|
|
661
|
+
|
|
662
|
+
except _HiddenConstraintViolation as e:
|
|
663
|
+
self._hidden_constraint_handling(e)
|
|
664
|
+
|
|
665
|
+
except SkipSolve as e:
|
|
666
|
+
self._skip_handling(e)
|
|
667
|
+
|
|
668
|
+
else:
|
|
669
|
+
self._if_succeeded(f_return)
|
|
670
|
+
|
|
671
|
+
self._postprocess()
|
|
672
|
+
|
|
673
|
+
# check interruption
|
|
674
|
+
self.opt._check_and_raise_interruption()
|
|
675
|
+
|
|
676
|
+
return f_return
|
|
677
|
+
|
|
678
|
+
def _get_solve_set(self):
|
|
679
|
+
return self._SolveSet(self)
|
|
680
|
+
|
|
681
|
+
# ===== run and setup =====
|
|
682
|
+
|
|
683
|
+
def _setting_status(self):
|
|
684
|
+
|
|
685
|
+
# noinspection PyMethodParameters
|
|
686
|
+
class _SettingStatus:
|
|
687
|
+
|
|
688
|
+
def __enter__(self_):
|
|
689
|
+
pass
|
|
690
|
+
|
|
691
|
+
def __exit__(self_, exc_type, exc_val, exc_tb):
|
|
692
|
+
if exc_type is not None:
|
|
693
|
+
if self.worker_status.value < WorkerStatus.crashed:
|
|
694
|
+
self.worker_status.value = WorkerStatus.crashed
|
|
695
|
+
else:
|
|
696
|
+
if self.worker_status.value < WorkerStatus.finishing:
|
|
697
|
+
self.worker_status.value = WorkerStatus.finishing
|
|
698
|
+
|
|
699
|
+
return _SettingStatus()
|
|
700
|
+
|
|
701
|
+
def run(self) -> None:
|
|
702
|
+
raise NotImplementedError
|
|
703
|
+
|
|
704
|
+
def _run(
|
|
705
|
+
self,
|
|
706
|
+
worker_idx: int | str,
|
|
707
|
+
worker_name: str,
|
|
708
|
+
history: History,
|
|
709
|
+
entire_status: WorkerStatus,
|
|
710
|
+
worker_status: WorkerStatus,
|
|
711
|
+
worker_status_list: list[WorkerStatus],
|
|
712
|
+
wait_other_process_setup: bool,
|
|
713
|
+
) -> None:
|
|
714
|
+
|
|
715
|
+
self.history = history
|
|
716
|
+
self.entire_status = entire_status
|
|
717
|
+
self.worker_status = worker_status
|
|
718
|
+
self._worker_index = worker_idx
|
|
719
|
+
self._worker_name = worker_name
|
|
720
|
+
self.worker_status_list = worker_status_list
|
|
721
|
+
|
|
722
|
+
class SettingStatusFinished:
|
|
723
|
+
|
|
724
|
+
# noinspection PyMethodParameters
|
|
725
|
+
def __enter__(self_):
|
|
726
|
+
pass
|
|
727
|
+
|
|
728
|
+
# noinspection PyMethodParameters
|
|
729
|
+
def __exit__(self_, exc_type, exc_val, exc_tb):
|
|
730
|
+
if exc_type is not None:
|
|
731
|
+
self.worker_status.value = WorkerStatus.crashed
|
|
732
|
+
|
|
733
|
+
import sys
|
|
734
|
+
from traceback import print_tb
|
|
735
|
+
print(
|
|
736
|
+
_(
|
|
737
|
+
'===== Exception raised in worker {worker_idx} =====',
|
|
738
|
+
worker_idx=worker_idx
|
|
739
|
+
),
|
|
740
|
+
file=sys.stderr
|
|
741
|
+
)
|
|
742
|
+
print_tb(exc_tb)
|
|
743
|
+
print(
|
|
744
|
+
_(
|
|
745
|
+
'{name}: {exc_val}',
|
|
746
|
+
name=exc_type.__name__,
|
|
747
|
+
exc_val=exc_val
|
|
748
|
+
),
|
|
749
|
+
file=sys.stderr
|
|
750
|
+
)
|
|
751
|
+
|
|
752
|
+
else:
|
|
753
|
+
self.worker_status.value = WorkerStatus.finished
|
|
754
|
+
|
|
755
|
+
logger.info(_(
|
|
756
|
+
en_message='worker `{worker}` started.',
|
|
757
|
+
worker=worker_name,
|
|
758
|
+
))
|
|
759
|
+
|
|
760
|
+
with SettingStatusFinished():
|
|
761
|
+
|
|
762
|
+
self.worker_status.value = WorkerStatus.initializing
|
|
763
|
+
|
|
764
|
+
self.worker_status.value = WorkerStatus.launching_fem
|
|
765
|
+
self.fem._setup_after_parallel(self)
|
|
766
|
+
|
|
767
|
+
if wait_other_process_setup:
|
|
768
|
+
self.worker_status.value = WorkerStatus.waiting
|
|
769
|
+
while True:
|
|
770
|
+
self._check_and_raise_interruption()
|
|
771
|
+
|
|
772
|
+
# 他のすべての worker_status が wait 以上になったら break
|
|
773
|
+
logger.debug([ws.value for ws in worker_status_list])
|
|
774
|
+
if all([ws.value >= WorkerStatus.waiting
|
|
775
|
+
for ws in worker_status_list]):
|
|
776
|
+
|
|
777
|
+
# リソースの競合等を避けるため
|
|
778
|
+
# break する前に index 秒待つ
|
|
779
|
+
if isinstance(worker_idx, str):
|
|
780
|
+
wait_second = 0.
|
|
781
|
+
else:
|
|
782
|
+
wait_second = int(worker_idx + 1)
|
|
783
|
+
sleep(wait_second)
|
|
784
|
+
break
|
|
785
|
+
|
|
786
|
+
sleep(1)
|
|
787
|
+
|
|
788
|
+
self.worker_status.value = WorkerStatus.running
|
|
789
|
+
|
|
790
|
+
self.run()
|
|
791
|
+
|
|
792
|
+
logger.info(_(
|
|
793
|
+
en_message='worker `{worker}` successfully finished!',
|
|
794
|
+
worker=worker_name,
|
|
795
|
+
))
|
|
796
|
+
|
|
797
|
+
def _logging(self):
|
|
798
|
+
|
|
799
|
+
# noinspection PyMethodParameters
|
|
800
|
+
class LoggingOutput:
|
|
801
|
+
def __enter__(self_):
|
|
802
|
+
self_.count = len(self.history.get_df()) + 1
|
|
803
|
+
logger.info(f'▼▼▼▼▼ solve {self_.count} start ▼▼▼▼▼')
|
|
804
|
+
|
|
805
|
+
def __exit__(self_, exc_type, exc_val, exc_tb):
|
|
806
|
+
logger.info(f'▲▲▲▲▲ solve {self_.count} end ▲▲▲▲▲\n')
|
|
807
|
+
|
|
808
|
+
return LoggingOutput()
|
|
809
|
+
|
|
810
|
+
def _load_problem_from_fem(self):
|
|
811
|
+
if self.fem._load_problem_from_fem and not self._done_load_problem_from_fem:
|
|
812
|
+
self.fem.load_variables(self)
|
|
813
|
+
self.fem.load_objectives(self)
|
|
814
|
+
self.fem.load_constraints(self)
|
|
815
|
+
self._done_load_problem_from_fem = True
|
|
816
|
+
|
|
817
|
+
# noinspection PyMethodMayBeStatic
|
|
818
|
+
def _get_additional_data(self) -> dict:
|
|
819
|
+
return dict()
|
|
820
|
+
|
|
821
|
+
def _collect_additional_data(self) -> dict:
|
|
822
|
+
additional_data = {}
|
|
823
|
+
additional_data.update(self._get_additional_data())
|
|
824
|
+
additional_data.update(self.fem._get_additional_data())
|
|
825
|
+
return additional_data
|
|
826
|
+
|
|
827
|
+
def _finalize_history(self):
|
|
828
|
+
if not self.history._finalized:
|
|
829
|
+
parameters = self.variable_manager.get_variables(
|
|
830
|
+
filter='parameter', format='raw'
|
|
831
|
+
)
|
|
832
|
+
self.history.finalize(
|
|
833
|
+
parameters,
|
|
834
|
+
list(self.objectives.keys()),
|
|
835
|
+
list(self.constraints.keys()),
|
|
836
|
+
[self.sub_fidelity_name] + list(self.sub_fidelity_models.keys()),
|
|
837
|
+
additional_data=self._collect_additional_data()
|
|
838
|
+
)
|
|
839
|
+
|
|
840
|
+
def _setup_before_parallel(self):
|
|
841
|
+
|
|
842
|
+
if not self._done_setup_before_parallel:
|
|
843
|
+
|
|
844
|
+
# check compatibility with fem if needed
|
|
845
|
+
variables = self.variable_manager.get_variables()
|
|
846
|
+
for var_name, variable in variables.items():
|
|
847
|
+
if variable.pass_to_fem:
|
|
848
|
+
self.fem._check_param_and_raise(var_name)
|
|
849
|
+
|
|
850
|
+
# resolve evaluation order
|
|
851
|
+
self.variable_manager.resolve()
|
|
852
|
+
|
|
853
|
+
self._done_setup_before_parallel = True
|
|
854
|
+
|
|
855
|
+
def _setup_after_parallel(self):
|
|
856
|
+
pass
|
|
857
|
+
|
|
858
|
+
def _finalize(self):
|
|
859
|
+
|
|
860
|
+
# check sub fidelity models
|
|
861
|
+
if self.sub_fidelity_models is None:
|
|
862
|
+
self.sub_fidelity_models = SubFidelityModels()
|
|
863
|
+
for sub_fidelity_model in self.sub_fidelity_models.values():
|
|
864
|
+
assert sub_fidelity_model.objectives.keys() == self.objectives.keys()
|
|
865
|
+
assert sub_fidelity_model.constraints.keys() == self.constraints.keys()
|
|
866
|
+
|
|
867
|
+
# finalize
|
|
868
|
+
self._load_problem_from_fem()
|
|
869
|
+
self._finalize_history()
|
|
870
|
+
|
|
871
|
+
# setup if needed
|
|
872
|
+
self._setup_before_parallel()
|
|
873
|
+
self._setup_after_parallel()
|
|
874
|
+
|
|
875
|
+
|
|
876
|
+
class SubFidelityModel(AbstractOptimizer):
|
|
877
|
+
pass
|
|
878
|
+
|
|
879
|
+
|
|
880
|
+
class SubFidelityModels(dict[str, SubFidelityModel]):
|
|
881
|
+
|
|
882
|
+
def _update(self, name, model: SubFidelityModel, fidelity: Fidelity):
|
|
883
|
+
model.sub_fidelity_name = name
|
|
884
|
+
model.fidelity = fidelity
|
|
885
|
+
self.update({name: model})
|