pyfemtet 0.9.5__py3-none-any.whl → 1.0.0a0__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 -19
- pyfemtet/opt/exceptions.py +45 -0
- pyfemtet/opt/femopt.py +602 -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} +490 -348
- 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/_base.py +0 -129
- pyfemtet/opt/interface/_surrogate_model_interface/__init__.py +8 -0
- pyfemtet/opt/interface/_surrogate_model_interface/base_surrogate_interface.py +59 -0
- pyfemtet/opt/interface/_surrogate_model_interface/botorch_interface.py +271 -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 +876 -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.0a0.dist-info}/METADATA +22 -24
- pyfemtet-1.0.0a0.dist-info/RECORD +173 -0
- pyfemtet-1.0.0a0.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/_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.0a0.dist-info}/LICENSE +0 -0
- {pyfemtet-0.9.5.dist-info → pyfemtet-1.0.0a0.dist-info}/LICENSE_THIRD_PARTY.txt +0 -0
- {pyfemtet-0.9.5.dist-info → pyfemtet-1.0.0a0.dist-info}/WHEEL +0 -0
|
@@ -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
|
-
)
|
|
@@ -1,434 +0,0 @@
|
|
|
1
|
-
# typing
|
|
2
|
-
from typing import Iterable
|
|
3
|
-
|
|
4
|
-
# built-in
|
|
5
|
-
import os
|
|
6
|
-
import inspect
|
|
7
|
-
import gc
|
|
8
|
-
|
|
9
|
-
# 3rd-party
|
|
10
|
-
import optuna
|
|
11
|
-
from optuna.trial import TrialState, FrozenTrial
|
|
12
|
-
from optuna.study import MaxTrialsCallback, Study
|
|
13
|
-
|
|
14
|
-
# pyfemtet relative
|
|
15
|
-
from pyfemtet.opt._femopt_core import OptimizationStatus, generate_lhs
|
|
16
|
-
from pyfemtet.opt.optimizer import AbstractOptimizer, logger, OptimizationMethodChecker
|
|
17
|
-
from pyfemtet.core import MeshError, ModelError, SolveError
|
|
18
|
-
from pyfemtet._message import Msg
|
|
19
|
-
|
|
20
|
-
# filter warnings
|
|
21
|
-
import warnings
|
|
22
|
-
from optuna.exceptions import ExperimentalWarning
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
optuna.logging.set_verbosity(optuna.logging.ERROR)
|
|
26
|
-
|
|
27
|
-
warnings.filterwarnings('ignore', category=ExperimentalWarning)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
class OptunaMethodChecker(OptimizationMethodChecker):
|
|
31
|
-
def check_multi_objective(self, raise_error=True): return True
|
|
32
|
-
def check_timeout(self, raise_error=True): return True
|
|
33
|
-
def check_parallel(self, raise_error=True): return True
|
|
34
|
-
def check_constraint(self, raise_error=True): return True
|
|
35
|
-
def check_strict_constraint(self, raise_error=True): return True
|
|
36
|
-
def check_skip(self, raise_error=True): return True
|
|
37
|
-
def check_seed(self, raise_error=True): return True
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
class OptunaOptimizer(AbstractOptimizer):
|
|
41
|
-
"""Optimizer using ```optuna```.
|
|
42
|
-
|
|
43
|
-
This class provides an interface for the optimization
|
|
44
|
-
engine using Optuna. For more details, please refer to
|
|
45
|
-
the Optuna documentation.
|
|
46
|
-
|
|
47
|
-
See Also:
|
|
48
|
-
https://optuna.readthedocs.io/en/stable/reference/index.html
|
|
49
|
-
|
|
50
|
-
Args:
|
|
51
|
-
sampler_class (optuna.samplers.BaseSampler, optional):
|
|
52
|
-
A sampler class from Optuna. If not specified,
|
|
53
|
-
```optuna.samplers.TPESampler``` is specified.
|
|
54
|
-
This defines the sampling strategy used during
|
|
55
|
-
optimization. Defaults to None.
|
|
56
|
-
sampler_kwargs (dict, optional):
|
|
57
|
-
A dictionary of keyword arguments to be passed to
|
|
58
|
-
the sampler class. This allows for customization
|
|
59
|
-
of the sampling process. Defaults to None.
|
|
60
|
-
add_init_method (str or Iterable[str], optional):
|
|
61
|
-
A method or a collection of methods to be added
|
|
62
|
-
during initialization. This can be used to specify
|
|
63
|
-
additional setup procedures.
|
|
64
|
-
Currently, the only valid value is 'LHS'
|
|
65
|
-
(using Latin Hypercube Sampling).
|
|
66
|
-
Defaults to None.
|
|
67
|
-
|
|
68
|
-
Warnings:
|
|
69
|
-
Do not include ```constraints_func``` in ```sampler_kwargs```.
|
|
70
|
-
It is generated and provided by :func:`FEMOpt.add_constraint`.
|
|
71
|
-
|
|
72
|
-
"""
|
|
73
|
-
|
|
74
|
-
def __init__(
|
|
75
|
-
self,
|
|
76
|
-
sampler_class: optuna.samplers.BaseSampler or None = None,
|
|
77
|
-
sampler_kwargs: dict or None = None,
|
|
78
|
-
add_init_method: str or Iterable[str] or None = None
|
|
79
|
-
):
|
|
80
|
-
super().__init__()
|
|
81
|
-
self.study_name = None
|
|
82
|
-
self.storage = None
|
|
83
|
-
self.study = None
|
|
84
|
-
self.optimize_callbacks = []
|
|
85
|
-
self.sampler_class = optuna.samplers.TPESampler if sampler_class is None else sampler_class
|
|
86
|
-
self.sampler_kwargs = dict() if sampler_kwargs is None else sampler_kwargs
|
|
87
|
-
self.additional_initial_parameter = []
|
|
88
|
-
self.additional_initial_methods = add_init_method if hasattr(add_init_method, '__iter__') else [add_init_method]
|
|
89
|
-
self.method_checker = OptunaMethodChecker(self)
|
|
90
|
-
self._temporary_storage = None
|
|
91
|
-
self._temporary_storage_path = '_pyfemtet_temporary_file.db'
|
|
92
|
-
|
|
93
|
-
def _objective(self, trial):
|
|
94
|
-
|
|
95
|
-
logger.info('')
|
|
96
|
-
logger.info(f'===== trial {1 + len(self.history.get_df())} ({len(self.history.get_df(valid_only=True))} succeeded trials) start =====')
|
|
97
|
-
|
|
98
|
-
# 中断の確認 (FAIL loop に陥る対策)
|
|
99
|
-
if self.entire_status.get() == OptimizationStatus.INTERRUPTING:
|
|
100
|
-
self.worker_status.set(OptimizationStatus.INTERRUPTING)
|
|
101
|
-
trial.study.stop() # 現在実行中の trial を最後にする
|
|
102
|
-
self._retry_counter = 0
|
|
103
|
-
return None # set TrialState FAIL
|
|
104
|
-
|
|
105
|
-
# candidate x and update parameters
|
|
106
|
-
logger.info('Searching new parameter set...')
|
|
107
|
-
for prm in self.variables.get_variables(format='raw', filter_parameter=True):
|
|
108
|
-
value = trial.suggest_float(
|
|
109
|
-
name=prm.name,
|
|
110
|
-
low=prm.lower_bound,
|
|
111
|
-
high=prm.upper_bound,
|
|
112
|
-
step=prm.step,
|
|
113
|
-
)
|
|
114
|
-
self.variables.variables[prm.name].value = value
|
|
115
|
-
|
|
116
|
-
# update expressions
|
|
117
|
-
self.variables.evaluate()
|
|
118
|
-
|
|
119
|
-
# message の設定
|
|
120
|
-
self.message = trial.user_attrs['message'] if 'message' in trial.user_attrs.keys() else ''
|
|
121
|
-
|
|
122
|
-
# fem 経由で変数を取得して constraint を計算する時のためにアップデート
|
|
123
|
-
df_fem = self.variables.get_variables(format='df', filter_pass_to_fem=True)
|
|
124
|
-
self.fem.update_parameter(df_fem)
|
|
125
|
-
x = self.variables.get_variables(format='values', filter_parameter=True)
|
|
126
|
-
|
|
127
|
-
# strict 拘束
|
|
128
|
-
strict_constraints = [cns for cns in self.constraints.values() if cns.strict]
|
|
129
|
-
for cns in strict_constraints:
|
|
130
|
-
feasible = True
|
|
131
|
-
cns_value = cns.calc(self.fem)
|
|
132
|
-
if cns.lb is not None:
|
|
133
|
-
feasible = feasible and (cns_value >= cns.lb)
|
|
134
|
-
if cns.ub is not None:
|
|
135
|
-
feasible = feasible and (cns.ub >= cns_value)
|
|
136
|
-
if not feasible:
|
|
137
|
-
logger.info('----- Out of constraint! -----')
|
|
138
|
-
logger.info(Msg.INFO_INFEASIBLE)
|
|
139
|
-
logger.info(f'Constraint: {cns.name}')
|
|
140
|
-
logger.info(self.variables.get_variables('dict', filter_parameter=True))
|
|
141
|
-
self._retry_counter += 1
|
|
142
|
-
self.message = f'Failed to calculate objectives because of the constraint violation: {cns.name}'
|
|
143
|
-
self.f(x, _record_infeasible=True)
|
|
144
|
-
raise optuna.TrialPruned() # set TrialState PRUNED because FAIL causes similar candidate loop.
|
|
145
|
-
|
|
146
|
-
# 計算
|
|
147
|
-
try:
|
|
148
|
-
_, _y, c = self.f(x) # f の中で info は出している
|
|
149
|
-
except (ModelError, MeshError, SolveError) as e:
|
|
150
|
-
# 中断の確認 (解析中に interrupt されている場合対策)
|
|
151
|
-
if self.entire_status.get() == OptimizationStatus.INTERRUPTING:
|
|
152
|
-
self.worker_status.set(OptimizationStatus.INTERRUPTING)
|
|
153
|
-
trial.study.stop() # 現在実行中の trial を最後にする
|
|
154
|
-
return None # set TrialState FAIL
|
|
155
|
-
|
|
156
|
-
logger.warning('----- Infeasible! -----')
|
|
157
|
-
logger.warning(Msg.INFO_INFEASIBLE)
|
|
158
|
-
logger.warning(f'Hidden Constraint ({type(e).__name__})')
|
|
159
|
-
logger.warning(self.variables.get_variables('dict', filter_parameter=True))
|
|
160
|
-
logger.warning('Please consider to determine the cause'
|
|
161
|
-
'of the above error and modify the model'
|
|
162
|
-
'or analysis.')
|
|
163
|
-
|
|
164
|
-
self._retry_counter += 1
|
|
165
|
-
self.message = f'Failed to calculate objectives because of the parameter broke the FEM model.'
|
|
166
|
-
self.f(x, _record_infeasible=True)
|
|
167
|
-
raise optuna.TrialPruned() # set TrialState PRUNED because FAIL causes similar candidate loop.
|
|
168
|
-
|
|
169
|
-
# 拘束 attr の更新
|
|
170
|
-
if len(self.constraints) > 0:
|
|
171
|
-
_c = [] # <= 0 is feasible
|
|
172
|
-
for (name, cns), c_value in zip(self.constraints.items(), c):
|
|
173
|
-
lb, ub = cns.lb, cns.ub
|
|
174
|
-
if lb is not None: # fun >= lb <=> lb - fun <= 0
|
|
175
|
-
_c.append(lb - c_value)
|
|
176
|
-
if ub is not None: # ub >= fun <=> fun - ub <= 0
|
|
177
|
-
_c.append(c_value - ub)
|
|
178
|
-
trial.set_user_attr('constraints', _c)
|
|
179
|
-
|
|
180
|
-
# 中断の確認 (解析中に interrupt されている場合対策)
|
|
181
|
-
if self.entire_status.get() == OptimizationStatus.INTERRUPTING:
|
|
182
|
-
self.worker_status.set(OptimizationStatus.INTERRUPTING)
|
|
183
|
-
trial.study.stop() # 現在実行中の trial を最後にする
|
|
184
|
-
self._retry_counter = 0
|
|
185
|
-
return None # set TrialState FAIL
|
|
186
|
-
|
|
187
|
-
# 結果
|
|
188
|
-
self._retry_counter = 0
|
|
189
|
-
return tuple(_y)
|
|
190
|
-
|
|
191
|
-
def _constraint(self, trial):
|
|
192
|
-
# if break trial without weak constraint calculation, return 1 (as infeasible).
|
|
193
|
-
if 'constraints' in trial.user_attrs.keys():
|
|
194
|
-
return trial.user_attrs['constraints']
|
|
195
|
-
else:
|
|
196
|
-
_c = []
|
|
197
|
-
for name, cns in self.constraints.items():
|
|
198
|
-
lb, ub = cns.lb, cns.ub
|
|
199
|
-
if lb is not None:
|
|
200
|
-
_c.append(1.)
|
|
201
|
-
if ub is not None:
|
|
202
|
-
_c.append(1.)
|
|
203
|
-
return _c
|
|
204
|
-
|
|
205
|
-
def _setup_before_parallel(self):
|
|
206
|
-
"""Create storage, study and set initial parameter."""
|
|
207
|
-
|
|
208
|
-
# create storage
|
|
209
|
-
self.study_name = 'pyfemtet-study'
|
|
210
|
-
storage_path = os.path.splitext(self.history.path)[0] + '.db' # history と同じところに保存
|
|
211
|
-
if self.is_cluster: # remote cluster なら scheduler の working dir に保存
|
|
212
|
-
storage_path = os.path.splitext(os.path.basename(self.history.path))[0] + '.db'
|
|
213
|
-
|
|
214
|
-
# callback to terminate
|
|
215
|
-
if self.n_trials is not None:
|
|
216
|
-
n_trials = self.n_trials
|
|
217
|
-
|
|
218
|
-
# restart である場合、追加 N 回と見做す
|
|
219
|
-
if self.history.is_restart:
|
|
220
|
-
n_existing_trials = len(self.history.get_df())
|
|
221
|
-
n_trials += n_existing_trials
|
|
222
|
-
|
|
223
|
-
self.optimize_callbacks.append(MaxTrialsCallback(n_trials, states=(TrialState.COMPLETE,)))
|
|
224
|
-
|
|
225
|
-
# if not restart, create study if storage is not exists
|
|
226
|
-
if not self.history.is_restart:
|
|
227
|
-
|
|
228
|
-
self.storage = optuna.integration.dask.DaskStorage(
|
|
229
|
-
f'sqlite:///{storage_path}',
|
|
230
|
-
)
|
|
231
|
-
|
|
232
|
-
self.study = optuna.create_study(
|
|
233
|
-
study_name=self.study_name,
|
|
234
|
-
storage=self.storage,
|
|
235
|
-
load_if_exists=True,
|
|
236
|
-
directions=['minimize'] * len(self.objectives),
|
|
237
|
-
)
|
|
238
|
-
|
|
239
|
-
# 初期値の設定
|
|
240
|
-
if len(self.study.trials) == 0: # リスタートでなければ
|
|
241
|
-
# ユーザーの指定した初期値
|
|
242
|
-
params = self.variables.get_variables('dict', filter_parameter=True)
|
|
243
|
-
self.study.enqueue_trial(params, user_attrs={"message": "initial"})
|
|
244
|
-
|
|
245
|
-
# add_initial_parameter で追加された初期値
|
|
246
|
-
for prm, prm_set_name in self.additional_initial_parameter:
|
|
247
|
-
if type(prm) is dict:
|
|
248
|
-
assert prm.keys() == params.keys(), Msg.ERR_INCONSISTENT_PARAMETER
|
|
249
|
-
else:
|
|
250
|
-
assert len(prm) == len(params.keys()), Msg.ERR_INCONSISTENT_PARAMETER
|
|
251
|
-
prm = dict(zip(params.keys(), prm))
|
|
252
|
-
|
|
253
|
-
self.study.enqueue_trial(
|
|
254
|
-
prm,
|
|
255
|
-
user_attrs={"message": prm_set_name}
|
|
256
|
-
)
|
|
257
|
-
|
|
258
|
-
# add_init で指定された方法による初期値
|
|
259
|
-
if 'LHS' in self.additional_initial_methods:
|
|
260
|
-
names = []
|
|
261
|
-
bounds = []
|
|
262
|
-
for i, row in self.get_parameter('df').iterrows():
|
|
263
|
-
names.append(row['name'])
|
|
264
|
-
lb = row['lower_bound']
|
|
265
|
-
ub = row['upper_bound']
|
|
266
|
-
bounds.append([lb, ub])
|
|
267
|
-
data = generate_lhs(bounds, seed=self.seed)
|
|
268
|
-
for datum in data:
|
|
269
|
-
d = {}
|
|
270
|
-
for name, v in zip(names, datum):
|
|
271
|
-
d[name] = v
|
|
272
|
-
self.study.enqueue_trial(
|
|
273
|
-
d, user_attrs={"message": "additional initial (Latin Hypercube Sampling)"}
|
|
274
|
-
)
|
|
275
|
-
|
|
276
|
-
# if is_restart, load study
|
|
277
|
-
else:
|
|
278
|
-
if not os.path.exists(storage_path):
|
|
279
|
-
raise FileNotFoundError(storage_path)
|
|
280
|
-
self.storage = optuna.integration.dask.DaskStorage(
|
|
281
|
-
f'sqlite:///{storage_path}',
|
|
282
|
-
)
|
|
283
|
-
|
|
284
|
-
# if TPESampler, create temporary study
|
|
285
|
-
# due to instability in case of many pruned trials.
|
|
286
|
-
from optuna.samplers import TPESampler
|
|
287
|
-
if issubclass(self.sampler_class, TPESampler):
|
|
288
|
-
|
|
289
|
-
import re
|
|
290
|
-
pattern = r'_\d+$'
|
|
291
|
-
|
|
292
|
-
while os.path.exists(self._temporary_storage_path):
|
|
293
|
-
name, ext = os.path.splitext(self._temporary_storage_path)
|
|
294
|
-
|
|
295
|
-
if bool(re.search(pattern, name)):
|
|
296
|
-
base = '_'.join(name.split('_')[:-1])
|
|
297
|
-
n = int(name.split('_')[-1])
|
|
298
|
-
self._temporary_storage_path = name + '_' + str(n+1) + ext
|
|
299
|
-
|
|
300
|
-
else:
|
|
301
|
-
self._temporary_storage_path = name + '_2' + ext
|
|
302
|
-
|
|
303
|
-
self._temporary_storage = optuna.integration.dask.DaskStorage(
|
|
304
|
-
f'sqlite:///{self._temporary_storage_path}',
|
|
305
|
-
)
|
|
306
|
-
|
|
307
|
-
study = optuna.load_study(
|
|
308
|
-
study_name=None,
|
|
309
|
-
storage=self.storage,
|
|
310
|
-
sampler=None,
|
|
311
|
-
)
|
|
312
|
-
|
|
313
|
-
_study = optuna.create_study(
|
|
314
|
-
study_name='tmp',
|
|
315
|
-
storage=self._temporary_storage,
|
|
316
|
-
load_if_exists=True,
|
|
317
|
-
directions=['minimize'] * len(self.objectives),
|
|
318
|
-
)
|
|
319
|
-
|
|
320
|
-
# Copy COMPLETE trials to temporary study.
|
|
321
|
-
existing_trials = study.get_trials(states=(optuna.trial.TrialState.COMPLETE,))
|
|
322
|
-
_study.add_trials(existing_trials)
|
|
323
|
-
|
|
324
|
-
def add_init_parameter(
|
|
325
|
-
self,
|
|
326
|
-
parameter: dict or Iterable,
|
|
327
|
-
name: str or None = None,
|
|
328
|
-
):
|
|
329
|
-
"""Add additional initial parameter for evaluate.
|
|
330
|
-
|
|
331
|
-
The parameter set is ignored if the main() is continued.
|
|
332
|
-
|
|
333
|
-
Args:
|
|
334
|
-
parameter (dict or Iterable): Parameter to evaluate before run optimization algorithm.
|
|
335
|
-
name (str or None): Optional. If specified, the name is saved in the history row. Default to None.
|
|
336
|
-
|
|
337
|
-
"""
|
|
338
|
-
if name is None:
|
|
339
|
-
name = 'additional initial'
|
|
340
|
-
else:
|
|
341
|
-
name = f'additional initial ({name})'
|
|
342
|
-
self.additional_initial_parameter.append([parameter, name])
|
|
343
|
-
|
|
344
|
-
def run(self):
|
|
345
|
-
"""Set random seed, sampler, study and run study.optimize()."""
|
|
346
|
-
|
|
347
|
-
# (re)set random seed
|
|
348
|
-
seed = self.seed
|
|
349
|
-
if seed is not None:
|
|
350
|
-
if self.subprocess_idx is not None:
|
|
351
|
-
seed += self.subprocess_idx
|
|
352
|
-
|
|
353
|
-
# restore sampler
|
|
354
|
-
if len(self.constraints) > 0:
|
|
355
|
-
self.sampler_kwargs.update(
|
|
356
|
-
constraints_func=self._constraint
|
|
357
|
-
)
|
|
358
|
-
if seed is not None:
|
|
359
|
-
self.sampler_kwargs.update(
|
|
360
|
-
seed=seed
|
|
361
|
-
)
|
|
362
|
-
parameters = inspect.signature(self.sampler_class.__init__).parameters
|
|
363
|
-
sampler_kwargs = dict()
|
|
364
|
-
for k, v in self.sampler_kwargs.items():
|
|
365
|
-
if k in parameters.keys():
|
|
366
|
-
sampler_kwargs.update({k: v})
|
|
367
|
-
sampler = self.sampler_class(
|
|
368
|
-
**sampler_kwargs
|
|
369
|
-
)
|
|
370
|
-
|
|
371
|
-
from pyfemtet.opt.optimizer._optuna._pof_botorch import PoFBoTorchSampler
|
|
372
|
-
if isinstance(sampler, PoFBoTorchSampler):
|
|
373
|
-
sampler._pyfemtet_constraints = [cns for cns in self.constraints.values() if cns.strict]
|
|
374
|
-
sampler._pyfemtet_optimizer = self
|
|
375
|
-
|
|
376
|
-
# load study
|
|
377
|
-
self.storage: optuna.storages.BaseStorage
|
|
378
|
-
studies = self.storage.get_all_studies()
|
|
379
|
-
if self.study_name in [s.study_name for s in studies]:
|
|
380
|
-
pass
|
|
381
|
-
|
|
382
|
-
elif len(studies) >= 1:
|
|
383
|
-
self.study_name = studies[-1].study_name
|
|
384
|
-
|
|
385
|
-
else:
|
|
386
|
-
raise ValueError('An empty db is passed.')
|
|
387
|
-
|
|
388
|
-
study = optuna.load_study(
|
|
389
|
-
study_name=self.study_name,
|
|
390
|
-
storage=self.storage,
|
|
391
|
-
sampler=sampler,
|
|
392
|
-
)
|
|
393
|
-
|
|
394
|
-
# use temporary storage or not
|
|
395
|
-
if self._temporary_storage is None:
|
|
396
|
-
# run
|
|
397
|
-
study.optimize(
|
|
398
|
-
self._objective,
|
|
399
|
-
timeout=self.timeout,
|
|
400
|
-
callbacks=self.optimize_callbacks,
|
|
401
|
-
)
|
|
402
|
-
|
|
403
|
-
else:
|
|
404
|
-
# load study
|
|
405
|
-
_study = optuna.load_study(
|
|
406
|
-
study_name="tmp",
|
|
407
|
-
storage=self._temporary_storage,
|
|
408
|
-
sampler=sampler,
|
|
409
|
-
)
|
|
410
|
-
|
|
411
|
-
# Add callback to coppy back each trial.
|
|
412
|
-
class CopyBack:
|
|
413
|
-
def __call__(self, _: Study, trial: FrozenTrial) -> None:
|
|
414
|
-
# Write back added trials to the existing study.
|
|
415
|
-
study.add_trial(trial)
|
|
416
|
-
self.optimize_callbacks.append(CopyBack())
|
|
417
|
-
|
|
418
|
-
# run
|
|
419
|
-
_study.optimize(
|
|
420
|
-
self._objective,
|
|
421
|
-
timeout=self.timeout,
|
|
422
|
-
callbacks=self.optimize_callbacks,
|
|
423
|
-
)
|
|
424
|
-
|
|
425
|
-
# clean up
|
|
426
|
-
try:
|
|
427
|
-
self._temporary_storage.remove_session()
|
|
428
|
-
del self._temporary_storage
|
|
429
|
-
del _study
|
|
430
|
-
gc.collect()
|
|
431
|
-
if os.path.exists(self._temporary_storage_path):
|
|
432
|
-
os.remove(self._temporary_storage_path)
|
|
433
|
-
except:
|
|
434
|
-
pass
|