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
pyfemtet/opt/optimizer/_base.py
DELETED
|
@@ -1,376 +0,0 @@
|
|
|
1
|
-
# typing
|
|
2
|
-
from abc import ABC, abstractmethod
|
|
3
|
-
from typing import Optional
|
|
4
|
-
|
|
5
|
-
# built-in
|
|
6
|
-
import traceback
|
|
7
|
-
from time import sleep
|
|
8
|
-
|
|
9
|
-
# 3rd-party
|
|
10
|
-
import numpy as np
|
|
11
|
-
|
|
12
|
-
# pyfemtet relative
|
|
13
|
-
from pyfemtet.opt.interface import FEMInterface
|
|
14
|
-
from pyfemtet.opt._femopt_core import OptimizationStatus, Objective, Constraint
|
|
15
|
-
from pyfemtet._message import Msg
|
|
16
|
-
from pyfemtet.opt.optimizer.parameter import ExpressionEvaluator, Parameter
|
|
17
|
-
|
|
18
|
-
# logger
|
|
19
|
-
from pyfemtet.logger import get_module_logger
|
|
20
|
-
|
|
21
|
-
logger = get_module_logger('opt.optimizer', __name__)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
class OptimizationMethodChecker:
|
|
25
|
-
"""Check implementation of PyFemtet functions."""
|
|
26
|
-
|
|
27
|
-
def __init__(self, opt):
|
|
28
|
-
self.opt = opt
|
|
29
|
-
|
|
30
|
-
def check_parallel(self, raise_error=True):
|
|
31
|
-
function = 'parallel-processing'
|
|
32
|
-
method = str(type(self.opt))
|
|
33
|
-
message = (Msg.ERR_NOT_IMPLEMENTED
|
|
34
|
-
+ f'method:{method}, function:{function}')
|
|
35
|
-
if raise_error:
|
|
36
|
-
raise NotImplementedError(message)
|
|
37
|
-
else:
|
|
38
|
-
logger.warning(message)
|
|
39
|
-
|
|
40
|
-
def check_timeout(self, raise_error=True):
|
|
41
|
-
function = 'timeout'
|
|
42
|
-
method = str(type(self.opt))
|
|
43
|
-
message = (Msg.ERR_NOT_IMPLEMENTED
|
|
44
|
-
+ f'method:{method}, function:{function}')
|
|
45
|
-
if raise_error:
|
|
46
|
-
raise NotImplementedError(message)
|
|
47
|
-
else:
|
|
48
|
-
logger.warning(message)
|
|
49
|
-
|
|
50
|
-
def check_multi_objective(self, raise_error=True):
|
|
51
|
-
function = 'multi-objective'
|
|
52
|
-
method = str(type(self.opt))
|
|
53
|
-
message = (Msg.ERR_NOT_IMPLEMENTED
|
|
54
|
-
+ f'method:{method}, function:{function}')
|
|
55
|
-
if raise_error:
|
|
56
|
-
raise NotImplementedError(message)
|
|
57
|
-
else:
|
|
58
|
-
logger.warning(message)
|
|
59
|
-
|
|
60
|
-
def check_strict_constraint(self, raise_error=True):
|
|
61
|
-
function = 'strict-constraint'
|
|
62
|
-
method = str(type(self.opt))
|
|
63
|
-
message = (Msg.ERR_NOT_IMPLEMENTED
|
|
64
|
-
+ f'method:{method}, function:{function}')
|
|
65
|
-
if raise_error:
|
|
66
|
-
raise NotImplementedError(message)
|
|
67
|
-
else:
|
|
68
|
-
logger.warning(message)
|
|
69
|
-
|
|
70
|
-
def check_constraint(self, raise_error=True):
|
|
71
|
-
function = 'constraint'
|
|
72
|
-
method = str(type(self.opt))
|
|
73
|
-
message = (Msg.ERR_NOT_IMPLEMENTED
|
|
74
|
-
+ f'method:{method}, function:{function}')
|
|
75
|
-
if raise_error:
|
|
76
|
-
raise NotImplementedError(message)
|
|
77
|
-
else:
|
|
78
|
-
logger.warning(message)
|
|
79
|
-
|
|
80
|
-
def check_skip(self, raise_error=True):
|
|
81
|
-
function = 'skip'
|
|
82
|
-
method = str(type(self.opt))
|
|
83
|
-
message = (Msg.ERR_NOT_IMPLEMENTED
|
|
84
|
-
+ f'method:{method}, function:{function}')
|
|
85
|
-
if raise_error:
|
|
86
|
-
raise NotImplementedError(message)
|
|
87
|
-
else:
|
|
88
|
-
logger.warning(message)
|
|
89
|
-
|
|
90
|
-
def check_seed(self, raise_error=True):
|
|
91
|
-
function = 'random seed setting'
|
|
92
|
-
method = str(type(self.opt))
|
|
93
|
-
message = (Msg.ERR_NOT_IMPLEMENTED
|
|
94
|
-
+ f'method:{method}, function:{function}')
|
|
95
|
-
if raise_error:
|
|
96
|
-
raise NotImplementedError(message)
|
|
97
|
-
else:
|
|
98
|
-
logger.warning(message)
|
|
99
|
-
|
|
100
|
-
def check_incomplete_bounds(self, raise_error=True):
|
|
101
|
-
function = 'optimize with no or incomplete bounds'
|
|
102
|
-
method = str(type(self.opt))
|
|
103
|
-
message = (Msg.ERR_NOT_IMPLEMENTED
|
|
104
|
-
+ f'method:{method}, function:{function}')
|
|
105
|
-
if raise_error:
|
|
106
|
-
raise NotImplementedError(message)
|
|
107
|
-
else:
|
|
108
|
-
logger.warning(message)
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
class AbstractOptimizer(ABC):
|
|
112
|
-
"""Abstract base class for an interface of optimization library.
|
|
113
|
-
|
|
114
|
-
Attributes:
|
|
115
|
-
fem (FEMInterface): The finite element method object.
|
|
116
|
-
fem_class (type): The class of the finite element method object.
|
|
117
|
-
fem_kwargs (dict): The keyword arguments used to instantiate the finite element method object.
|
|
118
|
-
variables (ExpressionEvaluator): The variables using optimization process including parameters.
|
|
119
|
-
objectives (dict[str, Objective]): A dictionary containing the objective functions used in the optimization.
|
|
120
|
-
constraints (dict[str, Constraint]): A dictionary containing the constraint functions used in the optimization.
|
|
121
|
-
history (History): An actor object that records the history of each iteration in the optimization process.
|
|
122
|
-
seed (int or None): The random seed used for random number generation during the optimization process.
|
|
123
|
-
|
|
124
|
-
"""
|
|
125
|
-
|
|
126
|
-
def __init__(self):
|
|
127
|
-
self.fem = None
|
|
128
|
-
self.fem_class = None
|
|
129
|
-
self.fem_kwargs = dict()
|
|
130
|
-
self.variables: ExpressionEvaluator = ExpressionEvaluator()
|
|
131
|
-
self.objectives: dict[str, Objective] = dict()
|
|
132
|
-
self.constraints: dict[str, Constraint] = dict()
|
|
133
|
-
self.entire_status = None # actor
|
|
134
|
-
self.history = None # actor
|
|
135
|
-
self.worker_status = None # actor
|
|
136
|
-
self.message = ''
|
|
137
|
-
self.seed = None
|
|
138
|
-
self.timeout = None
|
|
139
|
-
self.n_trials = None
|
|
140
|
-
self.is_cluster = False
|
|
141
|
-
self.subprocess_idx = None
|
|
142
|
-
self._exception = None
|
|
143
|
-
self.method_checker: OptimizationMethodChecker = OptimizationMethodChecker(self)
|
|
144
|
-
self._retry_counter = 0
|
|
145
|
-
|
|
146
|
-
# ===== algorithm specific methods =====
|
|
147
|
-
@abstractmethod
|
|
148
|
-
def run(self) -> None:
|
|
149
|
-
"""Start optimization."""
|
|
150
|
-
pass
|
|
151
|
-
|
|
152
|
-
# ----- FEMOpt interfaces -----
|
|
153
|
-
@abstractmethod
|
|
154
|
-
def _setup_before_parallel(self, *args, **kwargs):
|
|
155
|
-
"""Setup before parallel processes are launched."""
|
|
156
|
-
pass
|
|
157
|
-
|
|
158
|
-
# ===== calc =====
|
|
159
|
-
def f(self, x: np.ndarray, _record_infeasible=False) -> list[np.ndarray]:
|
|
160
|
-
"""Calculate objectives and constraints.
|
|
161
|
-
|
|
162
|
-
Args:
|
|
163
|
-
x (np.ndarray): Optimization parameters.
|
|
164
|
-
_record_infeasible (bool): If True, skip fem.update() and record self.generate_invalid_results().
|
|
165
|
-
|
|
166
|
-
Returns:
|
|
167
|
-
list[np.ndarray]:
|
|
168
|
-
The list of internal objective values,
|
|
169
|
-
un-normalized objective values and
|
|
170
|
-
constraint values.
|
|
171
|
-
|
|
172
|
-
"""
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
if isinstance(x, np.float64):
|
|
176
|
-
x = np.array([x])
|
|
177
|
-
|
|
178
|
-
# Optimizer の x の更新
|
|
179
|
-
self.set_parameter_values(x)
|
|
180
|
-
logger.info(f'input: {x}')
|
|
181
|
-
|
|
182
|
-
if not _record_infeasible:
|
|
183
|
-
# FEM の更新
|
|
184
|
-
try:
|
|
185
|
-
logger.info(f'Solving FEM...')
|
|
186
|
-
df_to_fem = self.variables.get_variables(
|
|
187
|
-
format='df',
|
|
188
|
-
filter_pass_to_fem=True
|
|
189
|
-
)
|
|
190
|
-
self.fem.update(df_to_fem)
|
|
191
|
-
|
|
192
|
-
except Exception as e:
|
|
193
|
-
logger.info(f'{type(e).__name__} : {e}')
|
|
194
|
-
logger.info(Msg.INFO_EXCEPTION_DURING_FEM_ANALYSIS)
|
|
195
|
-
logger.info(x)
|
|
196
|
-
raise e # may be just a ModelError, etc. Handling them in Concrete classes.
|
|
197
|
-
|
|
198
|
-
# y, _y, c の更新
|
|
199
|
-
y = [obj.calc(self.fem) for obj in self.objectives.values()]
|
|
200
|
-
|
|
201
|
-
_y = [obj.convert(value) for obj, value in zip(self.objectives.values(), y)]
|
|
202
|
-
|
|
203
|
-
c = [cns.calc(self.fem) for cns in self.constraints.values()]
|
|
204
|
-
|
|
205
|
-
else:
|
|
206
|
-
y, c = self.history.generate_hidden_infeasible_result()
|
|
207
|
-
_y = y
|
|
208
|
-
|
|
209
|
-
# register to history
|
|
210
|
-
df_to_opt = self.variables.get_variables(
|
|
211
|
-
format='df',
|
|
212
|
-
filter_parameter=True,
|
|
213
|
-
)
|
|
214
|
-
self.history.record(
|
|
215
|
-
df_to_opt,
|
|
216
|
-
self.objectives,
|
|
217
|
-
self.constraints,
|
|
218
|
-
y,
|
|
219
|
-
c,
|
|
220
|
-
self.message,
|
|
221
|
-
postprocess_func=self.fem._postprocess_func if not _record_infeasible else None,
|
|
222
|
-
postprocess_args=self.fem._create_postprocess_args() if not _record_infeasible else None,
|
|
223
|
-
)
|
|
224
|
-
|
|
225
|
-
logger.info(f'output: {y}')
|
|
226
|
-
|
|
227
|
-
return np.array(y), np.array(_y), np.array(c)
|
|
228
|
-
|
|
229
|
-
# ===== parameter processing =====
|
|
230
|
-
def get_parameter(self, format='dict'):
|
|
231
|
-
"""Returns the parameters in the specified format.
|
|
232
|
-
|
|
233
|
-
Args:
|
|
234
|
-
format (str, optional):
|
|
235
|
-
The desired format of the parameters.
|
|
236
|
-
Can be 'df' (DataFrame),
|
|
237
|
-
'values' (np.ndarray),
|
|
238
|
-
'dict' or
|
|
239
|
-
'raw' (list of Variable object).
|
|
240
|
-
Defaults to 'dict'.
|
|
241
|
-
|
|
242
|
-
Returns:
|
|
243
|
-
The parameters in the specified format.
|
|
244
|
-
|
|
245
|
-
Raises:
|
|
246
|
-
ValueError: If an invalid format is provided.
|
|
247
|
-
|
|
248
|
-
"""
|
|
249
|
-
return self.variables.get_variables(format=format, filter_parameter=True)
|
|
250
|
-
|
|
251
|
-
def set_parameter(self, params: dict[str, float]) -> None:
|
|
252
|
-
"""Update parameter.
|
|
253
|
-
|
|
254
|
-
Args:
|
|
255
|
-
params (dict):
|
|
256
|
-
Key is the name of parameter and
|
|
257
|
-
the value is the value of it.
|
|
258
|
-
The partial set is available.
|
|
259
|
-
|
|
260
|
-
"""
|
|
261
|
-
for name, value in params.items():
|
|
262
|
-
self.variables.variables[name].value = value
|
|
263
|
-
self.variables.evaluate()
|
|
264
|
-
|
|
265
|
-
def set_parameter_values(self, values: np.ndarray) -> None:
|
|
266
|
-
"""Update parameter with values.
|
|
267
|
-
|
|
268
|
-
Args:
|
|
269
|
-
values (np.ndarray): Values of all parameters.
|
|
270
|
-
|
|
271
|
-
"""
|
|
272
|
-
prm_names = self.variables.get_parameter_names()
|
|
273
|
-
assert len(values) == len(prm_names)
|
|
274
|
-
self.set_parameter({k: v for k, v in zip(prm_names, values)})
|
|
275
|
-
|
|
276
|
-
# ===== FEMOpt interfaces =====
|
|
277
|
-
def _reconstruct_fem(self, skip_reconstruct=False):
|
|
278
|
-
"""Reconstruct FEMInterface in a subprocess."""
|
|
279
|
-
# reconstruct fem
|
|
280
|
-
if not skip_reconstruct:
|
|
281
|
-
self.fem = self.fem_class(**self.fem_kwargs)
|
|
282
|
-
|
|
283
|
-
# COM 定数の restore
|
|
284
|
-
for obj in self.objectives.values():
|
|
285
|
-
obj._restore_constants()
|
|
286
|
-
for cns in self.constraints.values():
|
|
287
|
-
cns._restore_constants()
|
|
288
|
-
|
|
289
|
-
def _check_interruption(self):
|
|
290
|
-
""""""
|
|
291
|
-
if self.entire_status.get() == OptimizationStatus.INTERRUPTING:
|
|
292
|
-
self.worker_status.set(OptimizationStatus.INTERRUPTING)
|
|
293
|
-
self._finalize()
|
|
294
|
-
return True
|
|
295
|
-
else:
|
|
296
|
-
return False
|
|
297
|
-
|
|
298
|
-
def _finalize(self):
|
|
299
|
-
"""Destruct fem and set worker status."""
|
|
300
|
-
self.fem.quit()
|
|
301
|
-
if not self.worker_status.get() == OptimizationStatus.CRASHED:
|
|
302
|
-
self.worker_status.set(OptimizationStatus.TERMINATED)
|
|
303
|
-
|
|
304
|
-
# run via FEMOpt (considering parallel processing)
|
|
305
|
-
def _run(
|
|
306
|
-
self,
|
|
307
|
-
subprocess_idx, # 自身が何番目の並列プロセスであるかを示す連番
|
|
308
|
-
worker_status_list, # 他の worker の status オブジェクト
|
|
309
|
-
wait_setup, # 他の worker の status が ready になるまで待つか
|
|
310
|
-
skip_reconstruct=False, # reconstruct fem を行うかどうか
|
|
311
|
-
space_dir=None, # 特定の space_dir を使うかどうか
|
|
312
|
-
) -> Optional[Exception]:
|
|
313
|
-
|
|
314
|
-
# 自分の worker_status の取得
|
|
315
|
-
self.subprocess_idx = subprocess_idx
|
|
316
|
-
self.worker_status = worker_status_list[subprocess_idx]
|
|
317
|
-
self.worker_status.set(OptimizationStatus.LAUNCHING_FEM)
|
|
318
|
-
|
|
319
|
-
if self._check_interruption():
|
|
320
|
-
return None
|
|
321
|
-
|
|
322
|
-
# set_fem をはじめ、終了したらそれを示す
|
|
323
|
-
self._reconstruct_fem(skip_reconstruct)
|
|
324
|
-
self.fem._setup_after_parallel(opt=self, space_dir=space_dir)
|
|
325
|
-
self.worker_status.set(OptimizationStatus.WAIT_OTHER_WORKERS)
|
|
326
|
-
|
|
327
|
-
# wait_setup or not
|
|
328
|
-
if wait_setup:
|
|
329
|
-
while True:
|
|
330
|
-
if self._check_interruption():
|
|
331
|
-
return None
|
|
332
|
-
# 他のすべての worker_status が wait 以上になったら break
|
|
333
|
-
if all([ws.get() >= OptimizationStatus.WAIT_OTHER_WORKERS for ws in worker_status_list]):
|
|
334
|
-
# リソースの競合等を避けるため
|
|
335
|
-
# break する前に index 秒待つ
|
|
336
|
-
sleep(int(subprocess_idx))
|
|
337
|
-
break
|
|
338
|
-
sleep(1)
|
|
339
|
-
else:
|
|
340
|
-
if self._check_interruption():
|
|
341
|
-
return None
|
|
342
|
-
|
|
343
|
-
# set status running
|
|
344
|
-
if self.entire_status.get() < OptimizationStatus.RUNNING:
|
|
345
|
-
self.entire_status.set(OptimizationStatus.RUNNING)
|
|
346
|
-
self.worker_status.set(OptimizationStatus.RUNNING)
|
|
347
|
-
|
|
348
|
-
# run and finalize
|
|
349
|
-
try:
|
|
350
|
-
self.run()
|
|
351
|
-
except Exception as e:
|
|
352
|
-
logger.error("=================================")
|
|
353
|
-
logger.error("An unexpected error has occurred!")
|
|
354
|
-
logger.error("=================================")
|
|
355
|
-
logger.error(f'{type(e).__name__}: {e}')
|
|
356
|
-
traceback.print_exc()
|
|
357
|
-
self._exception = e
|
|
358
|
-
self.worker_status.set(OptimizationStatus.CRASHED)
|
|
359
|
-
finally:
|
|
360
|
-
self._finalize()
|
|
361
|
-
|
|
362
|
-
return self._exception
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
if __name__ == '__main__':
|
|
366
|
-
class Optimizer(AbstractOptimizer):
|
|
367
|
-
def run(self): pass
|
|
368
|
-
def _setup_before_parallel(self, *args, **kwargs): pass
|
|
369
|
-
|
|
370
|
-
opt = Optimizer()
|
|
371
|
-
opt.set_parameter(
|
|
372
|
-
dict(
|
|
373
|
-
prm1=0.,
|
|
374
|
-
prm2=1.,
|
|
375
|
-
)
|
|
376
|
-
)
|
|
@@ -1,220 +0,0 @@
|
|
|
1
|
-
from typing import Callable
|
|
2
|
-
from functools import partial
|
|
3
|
-
|
|
4
|
-
import numpy as np
|
|
5
|
-
|
|
6
|
-
import torch
|
|
7
|
-
from torch import Tensor
|
|
8
|
-
|
|
9
|
-
from optuna.study import Study
|
|
10
|
-
from optuna.trial import Trial
|
|
11
|
-
from optuna._transform import _SearchSpaceTransform
|
|
12
|
-
|
|
13
|
-
from botorch.acquisition import AcquisitionFunction
|
|
14
|
-
from botorch.optim.initializers import gen_batch_initial_conditions
|
|
15
|
-
|
|
16
|
-
from pyfemtet.opt._femopt_core import Constraint
|
|
17
|
-
from pyfemtet.opt.optimizer import OptunaOptimizer
|
|
18
|
-
from pyfemtet._message import Msg
|
|
19
|
-
|
|
20
|
-
from pyfemtet.logger import get_module_logger
|
|
21
|
-
|
|
22
|
-
logger = get_module_logger(__file__, __name__)
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
BotorchConstraint = Callable[[Tensor], Tensor]
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
# 拘束関数に pytorch の自動微分機能を適用するためのクラス
|
|
29
|
-
class GeneralFunctionWithForwardDifference(torch.autograd.Function):
|
|
30
|
-
"""自作関数を pytorch で自動微分するためのクラスです。
|
|
31
|
-
|
|
32
|
-
ユーザー定義関数を botorch 形式に変換する過程で微分の計算ができなくなるのでこれが必要です。
|
|
33
|
-
"""
|
|
34
|
-
|
|
35
|
-
@staticmethod
|
|
36
|
-
def forward(ctx, f, xs):
|
|
37
|
-
ys = f(xs)
|
|
38
|
-
ctx.save_for_backward(xs, ys)
|
|
39
|
-
ctx.f = f
|
|
40
|
-
return ys
|
|
41
|
-
|
|
42
|
-
@staticmethod
|
|
43
|
-
def backward(ctx, grad_output):
|
|
44
|
-
xs, ys = ctx.saved_tensors
|
|
45
|
-
f = ctx.f
|
|
46
|
-
dx = 0.001 # 入力は normalized なので決め打ちでよい
|
|
47
|
-
diff = []
|
|
48
|
-
xs = xs.detach() # xs に余計な計算履歴を残さないために、detachする。
|
|
49
|
-
for i in range(len(xs)):
|
|
50
|
-
xs[i] += dx
|
|
51
|
-
diff.append(torch.sum(grad_output * (f(xs) - ys)))
|
|
52
|
-
xs[i] -= dx
|
|
53
|
-
diff = torch.tensor(diff) / dx
|
|
54
|
-
return None, diff
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
# ユーザー定義関数 (pyfemtet.opt.Constraint) を受け取り、
|
|
58
|
-
# botorch で処理できる callable オブジェクトを作成するクラス
|
|
59
|
-
class ConvertedConstraint:
|
|
60
|
-
"""ユーザーが定義した Constraint を botorch で処理できる形式に変換します。
|
|
61
|
-
|
|
62
|
-
`callable()` は形状 `d` の 1 次元テンソルを受け取り、スカラーを返します。
|
|
63
|
-
"""
|
|
64
|
-
|
|
65
|
-
def __init__(self, constraint: Constraint, study: Study, bound: str, opt: OptunaOptimizer):
|
|
66
|
-
self._constraint: Constraint = constraint
|
|
67
|
-
self._study = study
|
|
68
|
-
self._bound = bound
|
|
69
|
-
self._opt = opt
|
|
70
|
-
|
|
71
|
-
def __call__(self, x: Tensor) -> Tensor: # BotorchConstraint
|
|
72
|
-
"""optimize_acqf() に渡される非線形拘束関数の処理です。
|
|
73
|
-
|
|
74
|
-
Args:
|
|
75
|
-
x (Tensor): Normalized parameters. Its length is d (== len(prm)).
|
|
76
|
-
|
|
77
|
-
Returns:
|
|
78
|
-
float Tensor. >= 0 is feasible.
|
|
79
|
-
|
|
80
|
-
"""
|
|
81
|
-
|
|
82
|
-
norm_x = x.detach().numpy()
|
|
83
|
-
c = evaluate_pyfemtet_cns(self._study, self._constraint, norm_x, self._opt)
|
|
84
|
-
if self._bound == 'lb':
|
|
85
|
-
return Tensor([c - self._constraint.lb])
|
|
86
|
-
elif self._bound == 'ub':
|
|
87
|
-
return Tensor([self._constraint.ub - c])
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
# list[pyfemtet.opt.Constraint] について、正規化された入力に対し、 feasible or not を返す関数
|
|
91
|
-
def is_feasible(study: Study, constraints: list[Constraint], norm_x: np.ndarray, opt: OptunaOptimizer) -> bool:
|
|
92
|
-
feasible = True
|
|
93
|
-
cns: Constraint
|
|
94
|
-
for cns in constraints:
|
|
95
|
-
c = evaluate_pyfemtet_cns(study, cns, norm_x, opt)
|
|
96
|
-
if cns.lb is not None:
|
|
97
|
-
if cns.lb > c:
|
|
98
|
-
feasible = False
|
|
99
|
-
break
|
|
100
|
-
if cns.ub is not None:
|
|
101
|
-
if cns.ub < c:
|
|
102
|
-
feasible = False
|
|
103
|
-
break
|
|
104
|
-
return feasible
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
# 正規化された入力を受けて pyfemtet.opt.Constraint を評価する関数
|
|
108
|
-
def evaluate_pyfemtet_cns(study: Study, cns: Constraint, norm_x: np.ndarray, opt: OptunaOptimizer) -> float:
|
|
109
|
-
"""Evaluate given constraint function by given NORMALIZED x.
|
|
110
|
-
|
|
111
|
-
Args:
|
|
112
|
-
study (Study): Optuna study. Use to detect search space from last trial's Distribution objects.
|
|
113
|
-
cns (Constraint): PyFemtet's format constraint.
|
|
114
|
-
norm_x (np.ndarray): NORMALIZED values of all parameters.
|
|
115
|
-
opt (OptunaOptimizer): PyFemtet's optimizer. Used for update values of `opt` and `fem` who may be used in `cns`.
|
|
116
|
-
|
|
117
|
-
Returns:
|
|
118
|
-
bool: feasible or not.
|
|
119
|
-
"""
|
|
120
|
-
# ===== unnormalize x =====
|
|
121
|
-
search_space = study.sampler.infer_relative_search_space(study, None)
|
|
122
|
-
trans = _SearchSpaceTransform(search_space, transform_0_1=True, transform_log=False, transform_step=False)
|
|
123
|
-
params = trans.untransform(norm_x)
|
|
124
|
-
|
|
125
|
-
# ===== update OptunaOptimizer and FEMInterface who is referenced by cns =====
|
|
126
|
-
|
|
127
|
-
# opt
|
|
128
|
-
opt.set_parameter(params)
|
|
129
|
-
|
|
130
|
-
# fem
|
|
131
|
-
if cns.using_fem:
|
|
132
|
-
df_to_fem = opt.variables.get_variables(format='df', filter_pass_to_fem=True)
|
|
133
|
-
opt.fem.update_parameter(df_to_fem)
|
|
134
|
-
|
|
135
|
-
# ===== calc cns =====
|
|
136
|
-
return cns.calc(opt.fem)
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
# botorch の optimize_acqf で非線形拘束を使えるようにするクラス。以下を備える。
|
|
140
|
-
# - 渡すパラメータ nonlinear_constraints を作成する
|
|
141
|
-
# - gen_initial_conditions で feasible なものを返すラッパー関数
|
|
142
|
-
class NonlinearInequalityConstraints:
|
|
143
|
-
"""botorch の optimize_acqf に parameter constraints を設定するための引数を作成します。"""
|
|
144
|
-
|
|
145
|
-
def __init__(self, study: Study, constraints: list[Constraint], opt: OptunaOptimizer):
|
|
146
|
-
self._study = study
|
|
147
|
-
self._constraints = constraints
|
|
148
|
-
self._opt = opt
|
|
149
|
-
|
|
150
|
-
self._nonlinear_inequality_constraints = []
|
|
151
|
-
cns: Constraint
|
|
152
|
-
for cns in self._constraints:
|
|
153
|
-
if cns.lb is not None:
|
|
154
|
-
cns_botorch = ConvertedConstraint(cns, self._study, 'lb', self._opt)
|
|
155
|
-
item = (lambda x: GeneralFunctionWithForwardDifference.apply(cns_botorch, x), True)
|
|
156
|
-
self._nonlinear_inequality_constraints.append(item)
|
|
157
|
-
if cns.ub is not None:
|
|
158
|
-
cns_botorch = ConvertedConstraint(cns, self._study, 'ub', self._opt)
|
|
159
|
-
item = (lambda x: GeneralFunctionWithForwardDifference.apply(cns_botorch, x), True)
|
|
160
|
-
self._nonlinear_inequality_constraints.append(item)
|
|
161
|
-
|
|
162
|
-
def _filter_feasible_conditions(self, ic_batch):
|
|
163
|
-
# List to store feasible initial conditions
|
|
164
|
-
feasible_ic_list = []
|
|
165
|
-
|
|
166
|
-
for each_num_restarts in ic_batch:
|
|
167
|
-
feasible_q_list = []
|
|
168
|
-
for each_q in each_num_restarts:
|
|
169
|
-
norm_x: np.ndarray = each_q.numpy() # normalized parameters
|
|
170
|
-
|
|
171
|
-
if is_feasible(self._study, self._constraints, norm_x, self._opt):
|
|
172
|
-
feasible_q_list.append(each_q) # Keep only feasible rows
|
|
173
|
-
|
|
174
|
-
if feasible_q_list: # Only add if there are feasible rows
|
|
175
|
-
feasible_ic_list.append(torch.stack(feasible_q_list))
|
|
176
|
-
|
|
177
|
-
# Stack feasible conditions back into tensor format
|
|
178
|
-
if feasible_ic_list:
|
|
179
|
-
return torch.stack(feasible_ic_list)
|
|
180
|
-
else:
|
|
181
|
-
return None # Return None if none are feasible
|
|
182
|
-
|
|
183
|
-
@staticmethod
|
|
184
|
-
def _generate_random_initial_conditions(shape):
|
|
185
|
-
# Generates random initial conditions with the same shape as ic_batch
|
|
186
|
-
return torch.rand(shape)
|
|
187
|
-
|
|
188
|
-
def _generate_feasible_initial_conditions(self, *args, **kwargs):
|
|
189
|
-
# A `num_restarts x q x d` tensor of initial conditions.
|
|
190
|
-
ic_batch = gen_batch_initial_conditions(*args, **kwargs)
|
|
191
|
-
feasible_ic_batch = self._filter_feasible_conditions(ic_batch)
|
|
192
|
-
|
|
193
|
-
while feasible_ic_batch is None:
|
|
194
|
-
# Generate new random ic_batch with the same shape
|
|
195
|
-
print('警告: gen_batch_initial_conditions() は feasible な初期値を提案しませんでした。'
|
|
196
|
-
'パラメータ提案を探索するための初期値をランダムに選定します。')
|
|
197
|
-
random_ic_batch = self._generate_random_initial_conditions(ic_batch.shape)
|
|
198
|
-
feasible_ic_batch = self._filter_feasible_conditions(random_ic_batch)
|
|
199
|
-
|
|
200
|
-
return feasible_ic_batch
|
|
201
|
-
|
|
202
|
-
def create_kwargs(self) -> dict:
|
|
203
|
-
"""
|
|
204
|
-
nonlinear_inequality_constraints:
|
|
205
|
-
非線形不等式制約を表すタプルのリスト。
|
|
206
|
-
タプルの最初の要素は、`callable(x) >= 0` という形式の制約を表す呼び出し可能オブジェクトです。
|
|
207
|
-
2 番目の要素はブール値で、点内制約の場合は `True`
|
|
208
|
-
制約は後で scipy ソルバーに渡されます。
|
|
209
|
-
この場合、`batch_initial_conditions` を渡す必要があります。
|
|
210
|
-
非線形不等式制約を使用するには、`batch_limit` を 1 に設定する必要もあります。
|
|
211
|
-
これは、`options` で指定されていない場合は自動的に行われます。
|
|
212
|
-
"""
|
|
213
|
-
return dict(
|
|
214
|
-
q=1,
|
|
215
|
-
options=dict(
|
|
216
|
-
batch_limit=1,
|
|
217
|
-
),
|
|
218
|
-
nonlinear_inequality_constraints=self._nonlinear_inequality_constraints,
|
|
219
|
-
ic_generator=self._generate_feasible_initial_conditions,
|
|
220
|
-
)
|