pyfemtet 0.9.5__py3-none-any.whl → 1.0.0b0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pyfemtet might be problematic. Click here for more details.
- pyfemtet/__init__.py +6 -1
- pyfemtet/_i18n/1. make_pot_and_update_po.bat +8 -0
- pyfemtet/_i18n/2. build_mo.bat +5 -0
- pyfemtet/_i18n/__init__.py +4 -0
- pyfemtet/_i18n/babel.cfg +2 -0
- pyfemtet/_i18n/i18n.py +37 -0
- pyfemtet/_i18n/locales/ja/LC_MESSAGES/messages.mo +0 -0
- pyfemtet/_i18n/locales/ja/LC_MESSAGES/messages.po +1020 -0
- pyfemtet/_i18n/locales/messages.pot +987 -0
- pyfemtet/{_message → _i18n}/messages.py +128 -41
- pyfemtet/_util/closing.py +19 -0
- pyfemtet/_util/dask_util.py +89 -7
- pyfemtet/_util/df_util.py +29 -0
- pyfemtet/_util/excel_macro_util.py +8 -3
- pyfemtet/_util/excel_parse_util.py +43 -23
- pyfemtet/_util/femtet_access_inspection.py +120 -0
- pyfemtet/{_femtet_config_util/autosave.py → _util/femtet_autosave.py} +7 -0
- pyfemtet/_util/femtet_exit.py +105 -0
- pyfemtet/_util/femtet_version.py +20 -0
- pyfemtet/_util/helper.py +94 -0
- pyfemtet/_util/process_util.py +107 -0
- pyfemtet/_util/str_enum.py +44 -0
- pyfemtet/core.py +15 -47
- pyfemtet/dispatch_extensions/__init__.py +8 -11
- pyfemtet/dispatch_extensions/_impl.py +42 -198
- pyfemtet/logger/__init__.py +8 -1
- pyfemtet/logger/_impl.py +5 -6
- pyfemtet/opt/__init__.py +3 -17
- pyfemtet/opt/exceptions.py +45 -0
- pyfemtet/opt/femopt.py +608 -0
- pyfemtet/opt/history/__init__.py +11 -0
- pyfemtet/opt/history/_history.py +1404 -0
- pyfemtet/opt/history/_hypervolume.py +169 -0
- pyfemtet/opt/history/_optimality.py +79 -0
- pyfemtet/opt/interface/__init__.py +17 -24
- pyfemtet/opt/interface/_base_interface.py +222 -0
- pyfemtet/opt/interface/_excel_interface/__init__.py +3 -0
- pyfemtet/opt/interface/_excel_interface/debug-excel-interface.xlsm +0 -0
- pyfemtet/opt/interface/_excel_interface/excel_interface.py +999 -0
- pyfemtet/opt/interface/_femtet_interface/__init__.py +3 -0
- pyfemtet/opt/interface/{_femtet_parametric.py → _femtet_interface/_femtet_parametric.py} +20 -12
- pyfemtet/opt/interface/{_femtet.py → _femtet_interface/femtet_interface.py} +505 -349
- pyfemtet/opt/interface/_femtet_with_nx_interface/__init__.py +5 -0
- pyfemtet/opt/interface/_femtet_with_nx_interface/femtet_with_nx_interface.py +230 -0
- pyfemtet/opt/interface/_femtet_with_nx_interface/model1.prt +0 -0
- pyfemtet/opt/interface/_femtet_with_nx_interface/model1.x_t +98 -0
- pyfemtet/opt/interface/{_femtet_with_nx → _femtet_with_nx_interface}/update_model.py +1 -3
- pyfemtet/opt/interface/_femtet_with_solidworks/__init__.py +5 -0
- pyfemtet/opt/interface/_femtet_with_solidworks/femtet_with_solidworks_interface.py +122 -0
- pyfemtet/opt/interface/_solidworks_interface/__init__.py +5 -0
- pyfemtet/opt/interface/_solidworks_interface/solidworks_interface.py +206 -0
- pyfemtet/opt/interface/_surrogate_model_interface/__init__.py +8 -0
- pyfemtet/opt/interface/_surrogate_model_interface/base_surrogate_interface.py +150 -0
- pyfemtet/opt/interface/_surrogate_model_interface/botorch_interface.py +298 -0
- pyfemtet/opt/interface/_surrogate_model_interface/debug-pof-botorch.reccsv +18 -0
- pyfemtet/opt/interface/_with_excel_settings/__init__.py +61 -0
- pyfemtet/opt/interface/_with_excel_settings/with_excel_settings.py +134 -0
- pyfemtet/opt/meta_script/YAML_Generator.xlsm +0 -0
- pyfemtet/opt/meta_script/__main__.py +58 -36
- pyfemtet/opt/optimizer/__init__.py +7 -9
- pyfemtet/opt/optimizer/_base_optimizer.py +885 -0
- pyfemtet/opt/optimizer/optuna_optimizer/__init__.py +9 -0
- pyfemtet/opt/optimizer/optuna_optimizer/_optuna_attribute.py +73 -0
- pyfemtet/opt/optimizer/optuna_optimizer/_optuna_optimizer.py +678 -0
- pyfemtet/opt/optimizer/optuna_optimizer/_pof_botorch/__init__.py +7 -0
- pyfemtet/opt/optimizer/optuna_optimizer/_pof_botorch/debug-pof-botorch.reccsv +18 -0
- pyfemtet/opt/optimizer/optuna_optimizer/_pof_botorch/enable_nonlinear_constraint.py +244 -0
- pyfemtet/opt/optimizer/optuna_optimizer/_pof_botorch/pof_botorch_sampler.py +1249 -0
- pyfemtet/opt/optimizer/optuna_optimizer/wat_ex14_parametric_jp.femprj +0 -0
- pyfemtet/opt/optimizer/scipy_optimizer/__init__.py +1 -0
- pyfemtet/opt/optimizer/scipy_optimizer/_scipy_optimizer.py +364 -0
- pyfemtet/opt/prediction/__init__.py +7 -0
- pyfemtet/opt/prediction/_botorch_utils.py +133 -0
- pyfemtet/opt/prediction/_gpytorch_modules_extension.py +142 -0
- pyfemtet/opt/prediction/_helper.py +155 -0
- pyfemtet/opt/prediction/_model.py +118 -0
- pyfemtet/opt/problem/problem.py +304 -0
- pyfemtet/opt/problem/variable_manager/__init__.py +20 -0
- pyfemtet/opt/problem/variable_manager/_string_as_expression.py +115 -0
- pyfemtet/opt/problem/variable_manager/_variable_manager.py +295 -0
- pyfemtet/opt/visualization/history_viewer/__main__.py +5 -0
- pyfemtet/opt/visualization/{_base.py → history_viewer/_base_application.py} +18 -13
- pyfemtet/opt/visualization/history_viewer/_common_pages.py +150 -0
- pyfemtet/opt/visualization/{_complex_components → history_viewer/_complex_components}/alert_region.py +10 -5
- pyfemtet/opt/visualization/{_complex_components → history_viewer/_complex_components}/control_femtet.py +16 -13
- pyfemtet/opt/visualization/{_complex_components → history_viewer/_complex_components}/main_graph.py +117 -47
- pyfemtet/opt/visualization/{_complex_components → history_viewer/_complex_components}/pm_graph.py +159 -138
- pyfemtet/opt/visualization/history_viewer/_process_monitor/_application.py +173 -0
- pyfemtet/opt/visualization/history_viewer/_process_monitor/_pages.py +291 -0
- pyfemtet/opt/visualization/{_wrapped_components → history_viewer/_wrapped_components}/dbc.py +1 -1
- pyfemtet/opt/visualization/{_wrapped_components → history_viewer/_wrapped_components}/dcc.py +1 -1
- pyfemtet/opt/visualization/{_wrapped_components → history_viewer/_wrapped_components}/html.py +1 -1
- pyfemtet/opt/visualization/history_viewer/result_viewer/__main__.py +5 -0
- pyfemtet/opt/visualization/{result_viewer/application.py → history_viewer/result_viewer/_application.py} +6 -6
- pyfemtet/opt/visualization/{result_viewer/pages.py → history_viewer/result_viewer/_pages.py} +106 -82
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08.csv +18 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08.db +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8.jpg +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8.log +45 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8.pdt +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_1.jpg +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_1.pdt +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_10.jpg +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_10.pdt +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_11.jpg +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_11.pdt +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_12.jpg +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_12.pdt +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_13.jpg +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_13.pdt +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_14.jpg +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_14.pdt +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_15.jpg +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_15.pdt +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_16.jpg +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_16.pdt +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_17.jpg +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_17.pdt +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_18.jpg +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_18.pdt +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_19.jpg +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_19.pdt +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_2.jpg +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_2.pdt +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_20.jpg +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_20.pdt +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_3.jpg +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_3.pdt +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_4.bgr +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_4.bnd +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_4.btr +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_4.jpg +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_4.mtl +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_4.pdt +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_4.prm +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_5.jpg +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_5.pdt +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_6.jpg +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_6.pdt +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_7.jpg +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_7.pdt +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_8.jpg +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_8.pdt +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_9.jpg +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_9.pdt +0 -0
- pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.femprj +0 -0
- pyfemtet/opt/visualization/plotter/main_figure_creator.py +536 -0
- pyfemtet/opt/visualization/plotter/pm_graph_creator.py +359 -0
- pyfemtet/opt/worker_status.py +120 -0
- {pyfemtet-0.9.5.dist-info → pyfemtet-1.0.0b0.dist-info}/METADATA +23 -24
- pyfemtet-1.0.0b0.dist-info/RECORD +172 -0
- pyfemtet-1.0.0b0.dist-info/entry_points.txt +3 -0
- pyfemtet/_femtet_config_util/exit.py +0 -59
- pyfemtet/_message/1. make_pot.bat +0 -11
- pyfemtet/_message/2. make_mo.bat +0 -6
- pyfemtet/_message/__init__.py +0 -5
- pyfemtet/_message/babel.cfg +0 -2
- pyfemtet/_message/locales/ja/LC_MESSAGES/messages.mo +0 -0
- pyfemtet/_message/locales/ja/LC_MESSAGES/messages.po +0 -570
- pyfemtet/_message/locales/messages.pot +0 -551
- pyfemtet/_warning.py +0 -87
- pyfemtet/brep/_impl.py +0 -18
- pyfemtet/opt/_femopt.py +0 -1007
- pyfemtet/opt/_femopt_core.py +0 -1169
- pyfemtet/opt/_test_utils/control_femtet.py +0 -39
- pyfemtet/opt/_test_utils/hyper_sphere.py +0 -24
- pyfemtet/opt/_test_utils/record_history.py +0 -130
- pyfemtet/opt/advanced_samples/excel_ui/(ref) original_project.femprj +0 -0
- pyfemtet/opt/advanced_samples/excel_ui/femtet-macro.xlsm +0 -0
- pyfemtet/opt/advanced_samples/excel_ui/pyfemtet-core.py +0 -291
- pyfemtet/opt/advanced_samples/excel_ui/test-pyfemtet-core.cmd +0 -22
- pyfemtet/opt/advanced_samples/restart/gal_ex13_parametric.femprj +0 -0
- pyfemtet/opt/advanced_samples/restart/gal_ex13_parametric_restart.py +0 -99
- pyfemtet/opt/advanced_samples/restart/gal_ex13_parametric_restart_jp.py +0 -102
- pyfemtet/opt/advanced_samples/surrogate_model/gal_ex13_create_training_data.py +0 -60
- pyfemtet/opt/advanced_samples/surrogate_model/gal_ex13_create_training_data_jp.py +0 -57
- pyfemtet/opt/advanced_samples/surrogate_model/gal_ex13_optimize_with_surrogate.py +0 -100
- pyfemtet/opt/advanced_samples/surrogate_model/gal_ex13_optimize_with_surrogate_jp.py +0 -90
- pyfemtet/opt/advanced_samples/surrogate_model/gal_ex13_parametric.femprj +0 -0
- pyfemtet/opt/interface/_base.py +0 -101
- pyfemtet/opt/interface/_excel_interface.py +0 -984
- pyfemtet/opt/interface/_femtet_excel.py +0 -141
- pyfemtet/opt/interface/_femtet_with_nx/__init__.py +0 -3
- pyfemtet/opt/interface/_femtet_with_nx/_interface.py +0 -178
- pyfemtet/opt/interface/_femtet_with_sldworks.py +0 -298
- pyfemtet/opt/interface/_surrogate/__init__.py +0 -5
- pyfemtet/opt/interface/_surrogate/_base.py +0 -129
- pyfemtet/opt/interface/_surrogate/_chaospy.py +0 -71
- pyfemtet/opt/interface/_surrogate/_singletaskgp.py +0 -71
- pyfemtet/opt/interface/_surrogate_excel.py +0 -102
- pyfemtet/opt/optimizer/_base.py +0 -376
- pyfemtet/opt/optimizer/_optuna/_botorch_patch/enable_nonlinear_constraint.py +0 -220
- pyfemtet/opt/optimizer/_optuna/_optuna.py +0 -434
- pyfemtet/opt/optimizer/_optuna/_pof_botorch.py +0 -1914
- pyfemtet/opt/optimizer/_scipy.py +0 -159
- pyfemtet/opt/optimizer/_scipy_scalar.py +0 -127
- pyfemtet/opt/optimizer/parameter.py +0 -113
- pyfemtet/opt/prediction/_base.py +0 -61
- pyfemtet/opt/prediction/single_task_gp.py +0 -119
- pyfemtet/opt/samples/femprj_sample/ParametricIF.femprj +0 -0
- pyfemtet/opt/samples/femprj_sample/ParametricIF.py +0 -29
- pyfemtet/opt/samples/femprj_sample/ParametricIF_test_result.reccsv +0 -13
- pyfemtet/opt/samples/femprj_sample/cad_ex01_NX.femprj +0 -0
- pyfemtet/opt/samples/femprj_sample/cad_ex01_NX.prt +0 -0
- pyfemtet/opt/samples/femprj_sample/cad_ex01_NX.py +0 -135
- pyfemtet/opt/samples/femprj_sample/cad_ex01_NX_test_result.reccsv +0 -23
- pyfemtet/opt/samples/femprj_sample/cad_ex01_SW.SLDPRT +0 -0
- pyfemtet/opt/samples/femprj_sample/cad_ex01_SW.femprj +0 -0
- pyfemtet/opt/samples/femprj_sample/cad_ex01_SW.py +0 -131
- pyfemtet/opt/samples/femprj_sample/cad_ex01_SW_test_result.reccsv +0 -23
- pyfemtet/opt/samples/femprj_sample/constrained_pipe.femprj +0 -0
- pyfemtet/opt/samples/femprj_sample/constrained_pipe.py +0 -96
- pyfemtet/opt/samples/femprj_sample/constrained_pipe_test_result.reccsv +0 -13
- pyfemtet/opt/samples/femprj_sample/gal_ex58_parametric.femprj +0 -0
- pyfemtet/opt/samples/femprj_sample/gal_ex58_parametric.py +0 -74
- pyfemtet/opt/samples/femprj_sample/gal_ex58_parametric_test_result.reccsv +0 -13
- pyfemtet/opt/samples/femprj_sample/gau_ex08_parametric.femprj +0 -0
- pyfemtet/opt/samples/femprj_sample/gau_ex08_parametric.py +0 -58
- pyfemtet/opt/samples/femprj_sample/gau_ex08_parametric_test_result.reccsv +0 -23
- pyfemtet/opt/samples/femprj_sample/gau_ex12_parametric.femprj +0 -0
- pyfemtet/opt/samples/femprj_sample/gau_ex12_parametric.py +0 -52
- pyfemtet/opt/samples/femprj_sample/her_ex40_parametric.femprj +0 -0
- pyfemtet/opt/samples/femprj_sample/her_ex40_parametric.py +0 -138
- pyfemtet/opt/samples/femprj_sample/her_ex40_parametric_test_result.reccsv +0 -18
- pyfemtet/opt/samples/femprj_sample/paswat_ex1_parametric.femprj +0 -0
- pyfemtet/opt/samples/femprj_sample/paswat_ex1_parametric.py +0 -60
- pyfemtet/opt/samples/femprj_sample/paswat_ex1_parametric_parallel.py +0 -61
- pyfemtet/opt/samples/femprj_sample/paswat_ex1_parametric_test_result.reccsv +0 -18
- pyfemtet/opt/samples/femprj_sample/wat_ex14_parametric.femprj +0 -0
- pyfemtet/opt/samples/femprj_sample/wat_ex14_parametric.py +0 -58
- pyfemtet/opt/samples/femprj_sample/wat_ex14_parametric_parallel.py +0 -58
- pyfemtet/opt/samples/femprj_sample/wat_ex14_parametric_test_result.reccsv +0 -18
- pyfemtet/opt/samples/femprj_sample_jp/ParametricIF_jp.femprj +0 -0
- pyfemtet/opt/samples/femprj_sample_jp/ParametricIF_jp.py +0 -29
- pyfemtet/opt/samples/femprj_sample_jp/cad_ex01_NX_jp.femprj +0 -0
- pyfemtet/opt/samples/femprj_sample_jp/cad_ex01_NX_jp.py +0 -129
- pyfemtet/opt/samples/femprj_sample_jp/cad_ex01_SW_jp.femprj +0 -0
- pyfemtet/opt/samples/femprj_sample_jp/cad_ex01_SW_jp.py +0 -125
- pyfemtet/opt/samples/femprj_sample_jp/constrained_pipe_jp.py +0 -93
- pyfemtet/opt/samples/femprj_sample_jp/gal_ex58_parametric_jp.femprj +0 -0
- pyfemtet/opt/samples/femprj_sample_jp/gal_ex58_parametric_jp.py +0 -70
- pyfemtet/opt/samples/femprj_sample_jp/gau_ex08_parametric_jp.femprj +0 -0
- pyfemtet/opt/samples/femprj_sample_jp/gau_ex08_parametric_jp.py +0 -57
- pyfemtet/opt/samples/femprj_sample_jp/gau_ex12_parametric_jp.py +0 -52
- pyfemtet/opt/samples/femprj_sample_jp/her_ex40_parametric_jp.femprj +0 -0
- pyfemtet/opt/samples/femprj_sample_jp/her_ex40_parametric_jp.py +0 -138
- pyfemtet/opt/samples/femprj_sample_jp/paswat_ex1_parametric_jp.femprj +0 -0
- pyfemtet/opt/samples/femprj_sample_jp/paswat_ex1_parametric_jp.py +0 -58
- pyfemtet/opt/samples/femprj_sample_jp/paswat_ex1_parametric_parallel_jp.py +0 -59
- pyfemtet/opt/samples/femprj_sample_jp/wat_ex14_parametric_jp.py +0 -56
- pyfemtet/opt/samples/femprj_sample_jp/wat_ex14_parametric_parallel_jp.py +0 -56
- pyfemtet/opt/visualization/_complex_components/main_figure_creator.py +0 -332
- pyfemtet/opt/visualization/_complex_components/pm_graph_creator.py +0 -201
- pyfemtet/opt/visualization/_process_monitor/application.py +0 -226
- pyfemtet/opt/visualization/_process_monitor/pages.py +0 -406
- pyfemtet/opt/visualization/_wrapped_components/__init__.py +0 -0
- pyfemtet/opt/visualization/result_viewer/__init__.py +0 -0
- pyfemtet-0.9.5.dist-info/RECORD +0 -158
- pyfemtet-0.9.5.dist-info/entry_points.txt +0 -3
- /pyfemtet/{_femtet_config_util → opt/problem}/__init__.py +0 -0
- /pyfemtet/{brep → opt/visualization/history_viewer}/__init__.py +0 -0
- /pyfemtet/opt/{_test_utils → visualization/history_viewer/_complex_components}/__init__.py +0 -0
- /pyfemtet/opt/{optimizer/_optuna → visualization/history_viewer/_process_monitor}/__init__.py +0 -0
- /pyfemtet/opt/{optimizer/_optuna/_botorch_patch → visualization/history_viewer/_wrapped_components}/__init__.py +0 -0
- /pyfemtet/opt/visualization/{_wrapped_components → history_viewer/_wrapped_components}/str_enum.py +0 -0
- /pyfemtet/opt/visualization/{result_viewer → history_viewer/result_viewer}/.gitignore +0 -0
- /pyfemtet/opt/visualization/{_complex_components → history_viewer/result_viewer}/__init__.py +0 -0
- /pyfemtet/opt/visualization/{_process_monitor → plotter}/__init__.py +0 -0
- /pyfemtet/opt/{samples/femprj_sample_jp/wat_ex14_parametric_jp.femprj → wat_ex14_parametric_jp.femprj} +0 -0
- {pyfemtet-0.9.5.dist-info → pyfemtet-1.0.0b0.dist-info}/LICENSE +0 -0
- {pyfemtet-0.9.5.dist-info → pyfemtet-1.0.0b0.dist-info}/LICENSE_THIRD_PARTY.txt +0 -0
- {pyfemtet-0.9.5.dist-info → pyfemtet-1.0.0b0.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,999 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
import gc
|
|
7
|
+
import tempfile
|
|
8
|
+
from time import sleep
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
import numpy as np
|
|
12
|
+
|
|
13
|
+
from win32com.client import DispatchEx, Dispatch
|
|
14
|
+
from win32com.client.dynamic import CDispatch
|
|
15
|
+
# noinspection PyUnresolvedReferences
|
|
16
|
+
from pythoncom import CoInitialize, CoUninitialize
|
|
17
|
+
# noinspection PyUnresolvedReferences
|
|
18
|
+
from pywintypes import com_error
|
|
19
|
+
from femtetutils import util
|
|
20
|
+
|
|
21
|
+
from pyfemtet._util.dask_util import *
|
|
22
|
+
from pyfemtet._util.process_util import *
|
|
23
|
+
from pyfemtet._util.excel_parse_util import *
|
|
24
|
+
from pyfemtet._util.excel_macro_util import *
|
|
25
|
+
from pyfemtet._util.femtet_autosave import *
|
|
26
|
+
from pyfemtet._i18n import _
|
|
27
|
+
|
|
28
|
+
from pyfemtet.opt.exceptions import *
|
|
29
|
+
from pyfemtet.opt.problem.variable_manager import SupportedVariableTypes
|
|
30
|
+
from pyfemtet.opt.interface._base_interface import COMInterface
|
|
31
|
+
|
|
32
|
+
from pyfemtet.logger import get_module_logger
|
|
33
|
+
from pyfemtet._util.helper import float_
|
|
34
|
+
|
|
35
|
+
if TYPE_CHECKING:
|
|
36
|
+
from pyfemtet.opt.optimizer import AbstractOptimizer
|
|
37
|
+
from pyfemtet.opt.problem.problem import Objective, Constraint
|
|
38
|
+
|
|
39
|
+
logger = get_module_logger('opt.interface')
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class WorkbookNotOpenedError(Exception):
|
|
43
|
+
pass
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class WorkSheetNotFoundError(Exception):
|
|
47
|
+
pass
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class ExcelInterface(COMInterface):
|
|
51
|
+
"""Excel を計算コアとして利用するためのクラス。
|
|
52
|
+
|
|
53
|
+
通常の有限要素法を Excel に
|
|
54
|
+
置き換えて使用することが可能です。
|
|
55
|
+
|
|
56
|
+
すでに Excel マクロと Femtet を
|
|
57
|
+
連携させた自動解析システムを
|
|
58
|
+
構築している場合、このクラスは
|
|
59
|
+
それをラップします。これにより、
|
|
60
|
+
PyFemtet を用いた最適化を
|
|
61
|
+
行う際に便利な機能を提供します。
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
input_xlsm_path (str or Path):
|
|
65
|
+
設計変数の定義を含む Excel ファイルのパスを指定
|
|
66
|
+
します。
|
|
67
|
+
|
|
68
|
+
input_sheet_name (str):
|
|
69
|
+
設計変数の定義を含むシートの名前を指定します。
|
|
70
|
+
|
|
71
|
+
output_xlsm_path (str or Path, optional):
|
|
72
|
+
目的関数の定義を含む Excel ファイルのパスを指定
|
|
73
|
+
します。指定しない場合は ``input_xlsm_path`` と
|
|
74
|
+
同じと見做します。
|
|
75
|
+
|
|
76
|
+
output_sheet_name (str, optional):
|
|
77
|
+
目的関数の定義を含む含むシートの名前を指定します。
|
|
78
|
+
指定しない場合は ``input_sheet_name`` と同じと見
|
|
79
|
+
做します。
|
|
80
|
+
|
|
81
|
+
procedure_xlsm_path (str, optional):
|
|
82
|
+
最適化ループ中に呼ぶ Excel マクロ関数を
|
|
83
|
+
含む xlsm のパスです。
|
|
84
|
+
指定しない場合は ``input_xlsm_path`` と
|
|
85
|
+
同じと見做します。
|
|
86
|
+
|
|
87
|
+
procedure_name (str, optional):
|
|
88
|
+
Excel マクロ関数名を指定します。指定しない場合は
|
|
89
|
+
``FemtetMacro.FemtetMain`` と見做します。
|
|
90
|
+
|
|
91
|
+
procedure_args (list or tuple, optional):
|
|
92
|
+
Excel マクロ関数に渡す引数をリストまたはタプルで
|
|
93
|
+
指定します。
|
|
94
|
+
|
|
95
|
+
connect_method (str, optional):
|
|
96
|
+
Excel との接続方法を指定します。 'auto' または
|
|
97
|
+
'new' が利用可能です。デフォルトは 'auto' です。
|
|
98
|
+
|
|
99
|
+
procedure_timeout (float or None, optional):
|
|
100
|
+
Excel マクロ関数のタイムアウト時間を秒単位で指定
|
|
101
|
+
します。 None の場合はタイムアウトなしとなります。
|
|
102
|
+
|
|
103
|
+
setup_xlsm_path (str or Path, optional):
|
|
104
|
+
セットアップ時に呼ぶ関数を含む xlsm のパスです。
|
|
105
|
+
指定しない場合は ``input_xlsm_path`` と
|
|
106
|
+
同じと見做します。
|
|
107
|
+
|
|
108
|
+
setup_procedure_name (str, optional):
|
|
109
|
+
セットアップ時に呼ぶマクロ関数名です。
|
|
110
|
+
指定しない場合、セットアップ時に何もしません。
|
|
111
|
+
|
|
112
|
+
setup_procedure_args (list or tuple, optional):
|
|
113
|
+
セットアップ時に呼ぶマクロ関数の引数です。
|
|
114
|
+
|
|
115
|
+
teardown_xlsm_path (str or Path, optional):
|
|
116
|
+
終了時に呼ぶ関数を含む xlsm のパスです。
|
|
117
|
+
指定しない場合は ``input_xlsm_path`` と
|
|
118
|
+
同じと見做します。
|
|
119
|
+
|
|
120
|
+
teardown_procedure_name (str, optional):
|
|
121
|
+
終了時に呼ぶマクロ関数名です。
|
|
122
|
+
指定しない場合、終了時に何もしません。
|
|
123
|
+
|
|
124
|
+
teardown_procedure_args (list or tuple, optional):
|
|
125
|
+
終了時に呼ぶマクロ関数の引数です。
|
|
126
|
+
|
|
127
|
+
visible (bool):
|
|
128
|
+
excel を可視化するかどうかです。
|
|
129
|
+
ただし、 True を指定した場合でもマクロの実行中は
|
|
130
|
+
不可視になります。
|
|
131
|
+
デフォルトは False です。
|
|
132
|
+
|
|
133
|
+
display_alerts (bool):
|
|
134
|
+
excel ダイアログを表示するかどうかです。
|
|
135
|
+
デバッグ目的の場合以外は True にしないでください。
|
|
136
|
+
デフォルトは False です。
|
|
137
|
+
|
|
138
|
+
terminate_excel_when_quit (bool):
|
|
139
|
+
終了時に Excel を終了するかどうかです。
|
|
140
|
+
指定しない場合、 connect_method が 'new' の場合
|
|
141
|
+
True とふるまい 'auto' の場合 False と振舞います。
|
|
142
|
+
|
|
143
|
+
interactive (bool):
|
|
144
|
+
excel を対話モードにするかどうかです。
|
|
145
|
+
False にすると、 visible == True であっても
|
|
146
|
+
自動化プロセス中にユーザーが誤って
|
|
147
|
+
Excel 本体を操作できないようにします。
|
|
148
|
+
デフォルトは True です。
|
|
149
|
+
|
|
150
|
+
Attributes:
|
|
151
|
+
input_xlsm_path (Path):
|
|
152
|
+
設計変数の定義を含む Excel ファイルのパス。
|
|
153
|
+
|
|
154
|
+
input_sheet_name (str):
|
|
155
|
+
設計変数の定義を含むシートの名前。
|
|
156
|
+
|
|
157
|
+
output_xlsm_path (Path):
|
|
158
|
+
目的関数の定義を含む Excel ファイルのパス。
|
|
159
|
+
|
|
160
|
+
output_sheet_name (str):
|
|
161
|
+
目的関数の定義を含む含むシートの名前。
|
|
162
|
+
|
|
163
|
+
procedure_name (str):
|
|
164
|
+
実行する Excel マクロ関数名。
|
|
165
|
+
|
|
166
|
+
procedure_args (list or tuple):
|
|
167
|
+
Excel マクロ関数に渡す引数のリストまたはタプル。
|
|
168
|
+
|
|
169
|
+
excel_connect_method (str):
|
|
170
|
+
接続方法。'new' または 'auto'。
|
|
171
|
+
|
|
172
|
+
procedure_timeout (float or None):
|
|
173
|
+
Excel マクロ関数の実行タイムアウト。
|
|
174
|
+
Noneの場合は無制限。
|
|
175
|
+
|
|
176
|
+
terminate_excel_when_quit (bool):
|
|
177
|
+
プログラム終了時に Excel を終了するかどうか。
|
|
178
|
+
connect_method が 'new' の場合 True,
|
|
179
|
+
'auto' の場合 False。
|
|
180
|
+
|
|
181
|
+
excel (CDispatch):
|
|
182
|
+
Excel の COM オブジェクト。
|
|
183
|
+
|
|
184
|
+
"""
|
|
185
|
+
|
|
186
|
+
input_xlsm_path: str # 操作対象の xlsm パス
|
|
187
|
+
input_sheet_name: str # 変数セルを定義しているシート名
|
|
188
|
+
output_xlsm_path: str # 操作対象の xlsm パス (指定しない場合、input と同一)
|
|
189
|
+
output_sheet_name: str # 計算結果セルを定義しているシート名 (指定しない場合、input と同一)
|
|
190
|
+
constraint_xlsm_path: str # 操作対象の xlsm パス (指定しない場合、input と同一)
|
|
191
|
+
constraint_sheet_name: str # 拘束関数セルを定義しているシート名 (指定しない場合、input と同一)
|
|
192
|
+
|
|
193
|
+
related_file_paths: list[str] # 並列時に個別に並列プロセスの space にアップロードする必要のあるパス
|
|
194
|
+
|
|
195
|
+
procedure_name: str # マクロ関数名(or モジュール名.関数名)
|
|
196
|
+
procedure_args: list # マクロ関数の引数
|
|
197
|
+
|
|
198
|
+
excel: CDispatch # Excel Application
|
|
199
|
+
wb_input: CDispatch # システムを構成する Workbook
|
|
200
|
+
sh_input: CDispatch # 変数の定義された WorkSheet
|
|
201
|
+
wb_output: CDispatch # システムを構成する Workbook
|
|
202
|
+
sh_output: CDispatch # 計算結果の定義された WorkSheet (sh_input と同じでもよい)
|
|
203
|
+
wb_constraint: CDispatch # システムを構成する Workbook
|
|
204
|
+
sh_constraint: CDispatch # 計算結果の定義された WorkSheet (sh_input と同じでもよい)
|
|
205
|
+
wb_procedure: CDispatch # システムを構成する Workbook
|
|
206
|
+
wb_setup: CDispatch # システムを構成する Workbook
|
|
207
|
+
wb_teardown: CDispatch # システムを構成する Workbook
|
|
208
|
+
|
|
209
|
+
visible: bool # excel を可視化するかどうか
|
|
210
|
+
display_alerts: bool # ダイアログを表示するかどうか
|
|
211
|
+
terminate_excel_when_quit: bool # 終了時に Excel を終了するかどうか
|
|
212
|
+
interactive: bool # excel を対話モードにするかどうか
|
|
213
|
+
|
|
214
|
+
_load_problem_from_fem = True
|
|
215
|
+
_excel_pid: int
|
|
216
|
+
_excel_hwnd: int
|
|
217
|
+
_with_femtet_autosave_setting: bool = True # Femtet の自動保存機能の自動設定を行うかどうか。Femtet がインストールされていない場合はオフにする。クラス変数なので、インスタンス化前に設定する。
|
|
218
|
+
_femtet_autosave_buffer: bool # Femtet の自動保存機能の一時退避場所。最適化中はオフにする。
|
|
219
|
+
com_members = {'excel': 'Excel.Application'}
|
|
220
|
+
|
|
221
|
+
setup_xlsm_path: str
|
|
222
|
+
setup_procedure_name: str
|
|
223
|
+
setup_procedure_args: list or tuple
|
|
224
|
+
teardown_xlsm_path: str
|
|
225
|
+
teardown_procedure_name: str
|
|
226
|
+
teardown_procedure_args: list or tuple
|
|
227
|
+
|
|
228
|
+
use_named_range: bool # input を定義したシートにおいて input の値を名前付き範囲で指定するかどうか。
|
|
229
|
+
force_override_when_load: bool # すでに指定されている parameter 等を excel の load 時に上書きするかどうか。
|
|
230
|
+
|
|
231
|
+
_tmp_dir: tempfile.TemporaryDirectory
|
|
232
|
+
|
|
233
|
+
def __init__(
|
|
234
|
+
self,
|
|
235
|
+
input_xlsm_path: str or Path,
|
|
236
|
+
input_sheet_name: str,
|
|
237
|
+
output_xlsm_path: str or Path = None,
|
|
238
|
+
output_sheet_name: str = None,
|
|
239
|
+
constraint_xlsm_path: str or Path = None,
|
|
240
|
+
constraint_sheet_name: str = None,
|
|
241
|
+
procedure_xlsm_path: str or Path = None,
|
|
242
|
+
procedure_name: str = None,
|
|
243
|
+
procedure_args: list or tuple = None,
|
|
244
|
+
connect_method: str = 'new', # or 'auto'
|
|
245
|
+
procedure_timeout: float or None = None,
|
|
246
|
+
setup_xlsm_path: str or Path = None,
|
|
247
|
+
setup_procedure_name: str = None,
|
|
248
|
+
setup_procedure_args: list or tuple = None,
|
|
249
|
+
teardown_xlsm_path: str or Path = None,
|
|
250
|
+
teardown_procedure_name: str = None,
|
|
251
|
+
teardown_procedure_args: list or tuple = None,
|
|
252
|
+
related_file_paths: list[str or Path] = None,
|
|
253
|
+
visible: bool = False,
|
|
254
|
+
display_alerts: bool = False,
|
|
255
|
+
terminate_excel_when_quit: bool = None,
|
|
256
|
+
interactive: bool = True,
|
|
257
|
+
use_named_range: bool = True,
|
|
258
|
+
force_override_when_load: bool = False,
|
|
259
|
+
):
|
|
260
|
+
|
|
261
|
+
show_experimental_warning("ExcelInterface")
|
|
262
|
+
|
|
263
|
+
def proc_path(path_):
|
|
264
|
+
if path_ is None:
|
|
265
|
+
return self._original_input_xlsm_path
|
|
266
|
+
else:
|
|
267
|
+
ret_ = os.path.abspath(path_)
|
|
268
|
+
assert os.path.isfile(ret_), f'{ret_} が見つかりません。'
|
|
269
|
+
return os.path.abspath(path_)
|
|
270
|
+
|
|
271
|
+
# 初期化
|
|
272
|
+
self._original_input_xlsm_path = os.path.abspath(str(input_xlsm_path))
|
|
273
|
+
assert os.path.isfile(self._original_input_xlsm_path), f'{self._original_input_xlsm_path} が見つかりません。'
|
|
274
|
+
self._original_output_xlsm_path = proc_path(output_xlsm_path)
|
|
275
|
+
self._original_constraint_xlsm_path = proc_path(constraint_xlsm_path)
|
|
276
|
+
self._original_procedure_xlsm_path = proc_path(procedure_xlsm_path)
|
|
277
|
+
self._original_setup_xlsm_path = proc_path(setup_xlsm_path)
|
|
278
|
+
self._original_teardown_xlsm_path = proc_path(teardown_xlsm_path)
|
|
279
|
+
self._original_related_file_paths = \
|
|
280
|
+
[proc_path(p) for p in related_file_paths] \
|
|
281
|
+
if related_file_paths is not None else []
|
|
282
|
+
|
|
283
|
+
self.input_xlsm_path = self._original_input_xlsm_path
|
|
284
|
+
self.output_xlsm_path = self._original_output_xlsm_path
|
|
285
|
+
self.constraint_xlsm_path = self._original_constraint_xlsm_path
|
|
286
|
+
self.procedure_xlsm_path = self._original_procedure_xlsm_path
|
|
287
|
+
self.setup_xlsm_path = self._original_setup_xlsm_path
|
|
288
|
+
self.teardown_xlsm_path = self._original_teardown_xlsm_path
|
|
289
|
+
self.related_file_paths = self._original_related_file_paths
|
|
290
|
+
|
|
291
|
+
self.input_sheet_name = input_sheet_name
|
|
292
|
+
self.output_sheet_name = output_sheet_name if output_sheet_name is not None else input_sheet_name
|
|
293
|
+
self.constraint_sheet_name = constraint_sheet_name or self.input_sheet_name
|
|
294
|
+
self.procedure_name = procedure_name
|
|
295
|
+
self.procedure_args = procedure_args or []
|
|
296
|
+
assert connect_method in ['new', 'auto']
|
|
297
|
+
self.excel_connect_method = connect_method
|
|
298
|
+
self.procedure_timeout = procedure_timeout
|
|
299
|
+
if terminate_excel_when_quit is None:
|
|
300
|
+
self.terminate_excel_when_quit = self.excel_connect_method == 'new'
|
|
301
|
+
else:
|
|
302
|
+
self.terminate_excel_when_quit = terminate_excel_when_quit
|
|
303
|
+
|
|
304
|
+
self.setup_procedure_name = setup_procedure_name
|
|
305
|
+
self.setup_procedure_args = setup_procedure_args or []
|
|
306
|
+
|
|
307
|
+
self.teardown_procedure_name = teardown_procedure_name
|
|
308
|
+
self.teardown_procedure_args = teardown_procedure_args or []
|
|
309
|
+
|
|
310
|
+
self.visible = visible
|
|
311
|
+
self.interactive = interactive
|
|
312
|
+
self.display_alerts = display_alerts
|
|
313
|
+
|
|
314
|
+
self.use_named_range = use_named_range
|
|
315
|
+
self.force_override_when_load = force_override_when_load
|
|
316
|
+
|
|
317
|
+
@property
|
|
318
|
+
def object_pass_to_fun(self):
|
|
319
|
+
"""The object pass to the first argument of user-defined objective functions.
|
|
320
|
+
|
|
321
|
+
Returns:
|
|
322
|
+
excel (CDispatch): COM object of Microsoft Excel.
|
|
323
|
+
"""
|
|
324
|
+
return self.excel
|
|
325
|
+
|
|
326
|
+
# ===== setup =====
|
|
327
|
+
def _setup_before_parallel(self) -> None:
|
|
328
|
+
# メインプロセスで、並列プロセスを開始する前に行う前処理
|
|
329
|
+
|
|
330
|
+
related_files = [self._original_input_xlsm_path]
|
|
331
|
+
|
|
332
|
+
if not _is_same_path(self._original_input_xlsm_path, self._original_output_xlsm_path):
|
|
333
|
+
related_files.append(self._original_output_xlsm_path)
|
|
334
|
+
|
|
335
|
+
if not _is_same_path(self._original_input_xlsm_path, self._original_constraint_xlsm_path):
|
|
336
|
+
related_files.append(self._original_constraint_xlsm_path)
|
|
337
|
+
|
|
338
|
+
if not _is_same_path(self._original_input_xlsm_path, self._original_procedure_xlsm_path):
|
|
339
|
+
related_files.append(self._original_procedure_xlsm_path)
|
|
340
|
+
|
|
341
|
+
if not _is_same_path(self._original_input_xlsm_path, self._original_setup_xlsm_path):
|
|
342
|
+
related_files.append(self._original_setup_xlsm_path)
|
|
343
|
+
|
|
344
|
+
if not _is_same_path(self._original_input_xlsm_path, self._original_teardown_xlsm_path):
|
|
345
|
+
related_files.append(self._original_teardown_xlsm_path)
|
|
346
|
+
|
|
347
|
+
related_files.extend(self._original_related_file_paths)
|
|
348
|
+
|
|
349
|
+
# dask worker 向け
|
|
350
|
+
self._distribute_files(related_files)
|
|
351
|
+
|
|
352
|
+
def _re_register_paths(self, suffix):
|
|
353
|
+
# self.hoge_path を dask worker space のファイルに変える
|
|
354
|
+
|
|
355
|
+
# paths を更新
|
|
356
|
+
# suffix の付与は connect_method が auto の場合
|
|
357
|
+
# 同名ファイルを開かないようにするための配慮
|
|
358
|
+
# output 等 == inputの場合、
|
|
359
|
+
# 最初に input を rename しているので
|
|
360
|
+
# すでに rename されている
|
|
361
|
+
self.input_xlsm_path = self._rename_and_get_path_on_worker_space(
|
|
362
|
+
self._original_input_xlsm_path, suffix)
|
|
363
|
+
self.output_xlsm_path = self._rename_and_get_path_on_worker_space(
|
|
364
|
+
self._original_output_xlsm_path, suffix, True)
|
|
365
|
+
self.constraint_xlsm_path = self._rename_and_get_path_on_worker_space(
|
|
366
|
+
self._original_constraint_xlsm_path, suffix, True)
|
|
367
|
+
self.procedure_xlsm_path = self._rename_and_get_path_on_worker_space(
|
|
368
|
+
self._original_procedure_xlsm_path, suffix, True)
|
|
369
|
+
self.setup_xlsm_path = self._rename_and_get_path_on_worker_space(
|
|
370
|
+
self._original_setup_xlsm_path, suffix, True)
|
|
371
|
+
self.teardown_xlsm_path = self._rename_and_get_path_on_worker_space(
|
|
372
|
+
self._original_teardown_xlsm_path, suffix, True)
|
|
373
|
+
|
|
374
|
+
def _setup_after_parallel(self, opt: AbstractOptimizer):
|
|
375
|
+
"""サブプロセス又はメインプロセスのサブスレッドで、最適化を開始する前の前処理"""
|
|
376
|
+
|
|
377
|
+
# 最適化中は femtet の autosave を無効にする
|
|
378
|
+
if self._with_femtet_autosave_setting:
|
|
379
|
+
self._femtet_autosave_buffer = _get_autosave_enabled()
|
|
380
|
+
_set_autosave_enabled(False)
|
|
381
|
+
|
|
382
|
+
# Excel の場合はスレッドが変わっただけでも初期化が必要
|
|
383
|
+
CoInitialize()
|
|
384
|
+
|
|
385
|
+
# 元のファイルを保護するため space のファイルを使用
|
|
386
|
+
suffix = self._get_worker_index_from_optimizer(opt)
|
|
387
|
+
self._re_register_paths(suffix)
|
|
388
|
+
|
|
389
|
+
# excel に繋ぐ
|
|
390
|
+
with Lock('connect-excel'):
|
|
391
|
+
self.connect_excel(self.excel_connect_method)
|
|
392
|
+
sleep(1)
|
|
393
|
+
|
|
394
|
+
# load_objective で optimizer に登録した Function は
|
|
395
|
+
# 少なくともスレッドが異なるので
|
|
396
|
+
# 現在のスレッドのオブジェクトに参照しなおす
|
|
397
|
+
obj: Objective
|
|
398
|
+
for obj_name, obj in opt.objectives.items():
|
|
399
|
+
if isinstance(obj.fun, _ScapeGoatObjective):
|
|
400
|
+
opt.objectives[obj_name].fun = self.objective_from_excel
|
|
401
|
+
|
|
402
|
+
cns: Constraint
|
|
403
|
+
for cns_name, cns in opt.constraints.items():
|
|
404
|
+
if isinstance(cns.fun, _ScapeGoatObjective):
|
|
405
|
+
opt.constraints[cns_name].fun = self.constraint_from_excel
|
|
406
|
+
|
|
407
|
+
# excel の setup 関数を必要なら実行する
|
|
408
|
+
if self.setup_procedure_name is not None:
|
|
409
|
+
|
|
410
|
+
logger.info(
|
|
411
|
+
_(
|
|
412
|
+
en_message='{procedure_kind} procedure {procedure_name} is running...',
|
|
413
|
+
jp_message='{procedure_kind} プロシージャ {procedure_name} を実行中です...',
|
|
414
|
+
procedure_kind='Setup',
|
|
415
|
+
procedure_name=self.setup_procedure_name
|
|
416
|
+
)
|
|
417
|
+
)
|
|
418
|
+
|
|
419
|
+
with Lock('excel_setup_procedure'):
|
|
420
|
+
try:
|
|
421
|
+
self.wb_setup.Activate()
|
|
422
|
+
sleep(0.1)
|
|
423
|
+
with watch_excel_macro_error(self.excel, timeout=self.procedure_timeout, restore_book=False):
|
|
424
|
+
self.excel.Run(
|
|
425
|
+
f'{self.setup_procedure_name}',
|
|
426
|
+
*self.setup_procedure_args
|
|
427
|
+
)
|
|
428
|
+
|
|
429
|
+
# 再計算
|
|
430
|
+
self.excel.CalculateFull()
|
|
431
|
+
sleep(1)
|
|
432
|
+
|
|
433
|
+
except com_error as e:
|
|
434
|
+
raise RuntimeError(
|
|
435
|
+
_(
|
|
436
|
+
en_message='Failed to run macro {procedure_name}. The original message is: {exception}',
|
|
437
|
+
jp_message='マクロ {procedure_name} の実行に失敗しました。エラーメッセージ: {exception}',
|
|
438
|
+
procedure_name=self.setup_procedure_name,
|
|
439
|
+
exception=e
|
|
440
|
+
)
|
|
441
|
+
)
|
|
442
|
+
|
|
443
|
+
def connect_excel(self, connect_method):
|
|
444
|
+
|
|
445
|
+
# ===== 新しい excel instance を起動 =====
|
|
446
|
+
# 起動
|
|
447
|
+
logger.info(_(
|
|
448
|
+
en_message='Launching and connecting to Microsoft Excel...',
|
|
449
|
+
jp_message='Microsoft Excel を起動して接続しています...',
|
|
450
|
+
))
|
|
451
|
+
if connect_method == 'auto':
|
|
452
|
+
self.excel = Dispatch('Excel.Application')
|
|
453
|
+
else:
|
|
454
|
+
self.excel = DispatchEx('Excel.Application')
|
|
455
|
+
logger.info(_(
|
|
456
|
+
en_message='The connection to Excel is established.',
|
|
457
|
+
jp_message='Excel への接続が確立されました。',
|
|
458
|
+
))
|
|
459
|
+
# FemtetRef.xla を開く
|
|
460
|
+
self.open_femtet_ref_xla()
|
|
461
|
+
sleep(0.5)
|
|
462
|
+
|
|
463
|
+
# 起動した excel の pid を記憶する
|
|
464
|
+
self._excel_hwnd = self.excel.hWnd
|
|
465
|
+
self._excel_pid = 0
|
|
466
|
+
while self._excel_pid == 0:
|
|
467
|
+
sleep(0.5)
|
|
468
|
+
self._excel_pid = _get_pid(self.excel.hWnd)
|
|
469
|
+
|
|
470
|
+
# 可視性の設定
|
|
471
|
+
self.excel.Visible = self.visible
|
|
472
|
+
self.excel.DisplayAlerts = self.display_alerts
|
|
473
|
+
self.excel.Interactive = self.interactive
|
|
474
|
+
sleep(0.5)
|
|
475
|
+
|
|
476
|
+
# open
|
|
477
|
+
self.excel.Workbooks.Open(self.input_xlsm_path)
|
|
478
|
+
sleep(0.1)
|
|
479
|
+
self.excel.Workbooks.Open(self.output_xlsm_path)
|
|
480
|
+
sleep(0.1)
|
|
481
|
+
self.excel.Workbooks.Open(self.constraint_xlsm_path)
|
|
482
|
+
sleep(0.1)
|
|
483
|
+
self.excel.Workbooks.Open(self.procedure_xlsm_path)
|
|
484
|
+
sleep(0.1)
|
|
485
|
+
self.excel.Workbooks.Open(self.setup_xlsm_path)
|
|
486
|
+
sleep(0.1)
|
|
487
|
+
self.excel.Workbooks.Open(self.teardown_xlsm_path)
|
|
488
|
+
sleep(0.1)
|
|
489
|
+
|
|
490
|
+
# book に参照設定を追加する
|
|
491
|
+
self.add_femtet_macro_reference(self.wb_input)
|
|
492
|
+
self.add_femtet_macro_reference(self.wb_output)
|
|
493
|
+
self.add_femtet_macro_reference(self.wb_setup)
|
|
494
|
+
self.add_femtet_macro_reference(self.wb_teardown)
|
|
495
|
+
self.add_femtet_macro_reference(self.wb_constraint)
|
|
496
|
+
|
|
497
|
+
def open_femtet_ref_xla(self):
|
|
498
|
+
|
|
499
|
+
# get 64 bit
|
|
500
|
+
xla_file_path = r'C:\Program Files\Microsoft Office\root\Office16\XLSTART\FemtetRef.xla'
|
|
501
|
+
|
|
502
|
+
# if not exist, get 32bit
|
|
503
|
+
if not os.path.exists(xla_file_path):
|
|
504
|
+
xla_file_path = r'C:\Program Files (x86)\Microsoft Office\root\Office16\XLSTART\FemtetRef.xla'
|
|
505
|
+
|
|
506
|
+
# certify
|
|
507
|
+
if not os.path.exists(xla_file_path):
|
|
508
|
+
raise FileNotFoundError(
|
|
509
|
+
_(
|
|
510
|
+
en_message='Femtet XLA file not found: {xla_file_path}',
|
|
511
|
+
jp_message='Femtet XLA ファイルが見つかりません: {xla_file_path}',
|
|
512
|
+
xla_file_path=xla_file_path
|
|
513
|
+
)
|
|
514
|
+
)
|
|
515
|
+
|
|
516
|
+
# self.excel.Workbooks.Add(xla_file_path)
|
|
517
|
+
self.excel.Workbooks.Open(xla_file_path, ReadOnly=True)
|
|
518
|
+
|
|
519
|
+
@staticmethod
|
|
520
|
+
def add_femtet_macro_reference(wb):
|
|
521
|
+
|
|
522
|
+
# search
|
|
523
|
+
ref_file_2 = os.path.abspath(util._get_femtetmacro_dllpath())
|
|
524
|
+
contain_2 = False
|
|
525
|
+
for ref in wb.VBProject.References:
|
|
526
|
+
if ref.Description is not None:
|
|
527
|
+
if ref.Description == 'FemtetMacro': # FemtetMacro
|
|
528
|
+
contain_2 = True
|
|
529
|
+
break
|
|
530
|
+
# add
|
|
531
|
+
if not contain_2:
|
|
532
|
+
wb.VBProject.References.AddFromFile(ref_file_2)
|
|
533
|
+
|
|
534
|
+
@staticmethod
|
|
535
|
+
def remove_femtet_ref_xla(wb):
|
|
536
|
+
# search
|
|
537
|
+
for ref in wb.VBProject.References:
|
|
538
|
+
if ref.Description is not None:
|
|
539
|
+
if ref.Description == 'FemtetMacro': # FemtetMacro
|
|
540
|
+
wb.VBProject.References.Remove(ref)
|
|
541
|
+
|
|
542
|
+
# ===== load =====
|
|
543
|
+
def load_variables(self, opt: AbstractOptimizer, raise_if_no_keyword=True) -> None:
|
|
544
|
+
|
|
545
|
+
df = ParseAsParameter.parse(
|
|
546
|
+
self.input_xlsm_path,
|
|
547
|
+
self.input_sheet_name,
|
|
548
|
+
raise_if_no_keyword,
|
|
549
|
+
)
|
|
550
|
+
|
|
551
|
+
for i, row in df.iterrows():
|
|
552
|
+
|
|
553
|
+
# use(optional)
|
|
554
|
+
use = True
|
|
555
|
+
if ParseAsParameter.use in df.columns:
|
|
556
|
+
_use = row[ParseAsParameter.use]
|
|
557
|
+
use = False if _is_cell_value_empty(_use) else bool(_use) # bool or NaN
|
|
558
|
+
|
|
559
|
+
# name
|
|
560
|
+
name = str(row[ParseAsParameter.name])
|
|
561
|
+
|
|
562
|
+
# if the variable is already added by
|
|
563
|
+
# add_parameter or add_expression,
|
|
564
|
+
# use it.
|
|
565
|
+
if not self.force_override_when_load:
|
|
566
|
+
if name in opt.variable_manager.get_variables():
|
|
567
|
+
continue
|
|
568
|
+
|
|
569
|
+
# value
|
|
570
|
+
value = float_(row[ParseAsParameter.value])
|
|
571
|
+
|
|
572
|
+
# if 'choices' column exists and is not empty, use as Categorical.
|
|
573
|
+
kind = 'Numerical'
|
|
574
|
+
if ParseAsParameter.choices in df.columns:
|
|
575
|
+
if row[ParseAsParameter.choices] != _EMPTY_CHOICE:
|
|
576
|
+
kind = 'Categorical'
|
|
577
|
+
|
|
578
|
+
if kind == 'Numerical':
|
|
579
|
+
|
|
580
|
+
# lb (optional)
|
|
581
|
+
lb = None
|
|
582
|
+
if ParseAsParameter.lb in df.columns:
|
|
583
|
+
lb = row[ParseAsParameter.lb]
|
|
584
|
+
lb = None if _is_cell_value_empty(lb) else float(lb)
|
|
585
|
+
|
|
586
|
+
# ub (optional)
|
|
587
|
+
ub = None
|
|
588
|
+
if ParseAsParameter.ub in df.columns:
|
|
589
|
+
ub = row[ParseAsParameter.ub]
|
|
590
|
+
ub = None if _is_cell_value_empty(ub) else float(ub)
|
|
591
|
+
|
|
592
|
+
# step (optional)
|
|
593
|
+
step = None
|
|
594
|
+
if ParseAsParameter.step in df.columns:
|
|
595
|
+
step = row[ParseAsParameter.step]
|
|
596
|
+
step = None if _is_cell_value_empty(step) else float(step)
|
|
597
|
+
|
|
598
|
+
opt.add_parameter(
|
|
599
|
+
name=name,
|
|
600
|
+
initial_value=value,
|
|
601
|
+
lower_bound=lb,
|
|
602
|
+
upper_bound=ub,
|
|
603
|
+
step=step,
|
|
604
|
+
fix=not use,
|
|
605
|
+
)
|
|
606
|
+
|
|
607
|
+
elif kind == 'Categorical':
|
|
608
|
+
|
|
609
|
+
# choices
|
|
610
|
+
choices = row[ParseAsParameter.choices]
|
|
611
|
+
assert choices != _EMPTY_CHOICE
|
|
612
|
+
opt.add_categorical_parameter(
|
|
613
|
+
name=name,
|
|
614
|
+
initial_value=value,
|
|
615
|
+
choices=choices,
|
|
616
|
+
fix=not use,
|
|
617
|
+
)
|
|
618
|
+
|
|
619
|
+
else:
|
|
620
|
+
raise NotImplementedError
|
|
621
|
+
|
|
622
|
+
def load_objectives(self, opt: AbstractOptimizer, raise_if_no_keyword=True):
|
|
623
|
+
|
|
624
|
+
df = ParseAsObjective.parse(
|
|
625
|
+
self.output_xlsm_path,
|
|
626
|
+
self.output_sheet_name,
|
|
627
|
+
raise_if_no_keyword,
|
|
628
|
+
)
|
|
629
|
+
|
|
630
|
+
for i, row in df.iterrows():
|
|
631
|
+
|
|
632
|
+
# use(optional)
|
|
633
|
+
use = True
|
|
634
|
+
if ParseAsObjective.use in df.columns:
|
|
635
|
+
_use = row[ParseAsObjective.use]
|
|
636
|
+
use = False if _is_cell_value_empty(_use) else bool(_use) # bool or NaN
|
|
637
|
+
|
|
638
|
+
# name
|
|
639
|
+
name = str(row[ParseAsObjective.name])
|
|
640
|
+
|
|
641
|
+
# if the objective is already added by
|
|
642
|
+
# add_objective, use it.
|
|
643
|
+
if not self.force_override_when_load:
|
|
644
|
+
if name in opt.objectives.keys():
|
|
645
|
+
continue
|
|
646
|
+
|
|
647
|
+
# direction
|
|
648
|
+
direction = row[ParseAsObjective.direction]
|
|
649
|
+
assert not _is_cell_value_empty(direction), 'direction is empty.'
|
|
650
|
+
try:
|
|
651
|
+
direction = float(direction)
|
|
652
|
+
except ValueError:
|
|
653
|
+
direction = str(direction).lower()
|
|
654
|
+
assert direction in ['minimize', 'maximize']
|
|
655
|
+
|
|
656
|
+
if use:
|
|
657
|
+
# objective を作る
|
|
658
|
+
opt.add_objective(
|
|
659
|
+
name=name,
|
|
660
|
+
direction=direction,
|
|
661
|
+
fun=_ScapeGoatObjective(),
|
|
662
|
+
kwargs=dict(name=name),
|
|
663
|
+
)
|
|
664
|
+
|
|
665
|
+
def load_constraints(self, opt: AbstractOptimizer, raise_if_no_keyword=False):
|
|
666
|
+
|
|
667
|
+
df = ParseAsConstraint.parse(
|
|
668
|
+
self.constraint_xlsm_path,
|
|
669
|
+
self.constraint_sheet_name,
|
|
670
|
+
raise_if_no_keyword,
|
|
671
|
+
)
|
|
672
|
+
|
|
673
|
+
for i, row in df.iterrows():
|
|
674
|
+
|
|
675
|
+
# use(optional)
|
|
676
|
+
use = True
|
|
677
|
+
if ParseAsConstraint.use in df.columns:
|
|
678
|
+
_use = row[ParseAsConstraint.use]
|
|
679
|
+
use = False if _is_cell_value_empty(_use) else bool(_use) # bool or NaN
|
|
680
|
+
|
|
681
|
+
# name
|
|
682
|
+
name = str(row[ParseAsConstraint.name])
|
|
683
|
+
|
|
684
|
+
# if the constraint is already added by
|
|
685
|
+
# add_constraint, use it.
|
|
686
|
+
if not self.force_override_when_load:
|
|
687
|
+
if name in opt.constraints.keys():
|
|
688
|
+
continue
|
|
689
|
+
|
|
690
|
+
# lb (optional)
|
|
691
|
+
lb = None
|
|
692
|
+
if ParseAsConstraint.lb in df.columns:
|
|
693
|
+
lb = row[ParseAsConstraint.lb]
|
|
694
|
+
lb = None if _is_cell_value_empty(lb) else float(lb)
|
|
695
|
+
|
|
696
|
+
# ub (optional)
|
|
697
|
+
ub = None
|
|
698
|
+
if ParseAsConstraint.ub in df.columns:
|
|
699
|
+
ub = row[ParseAsConstraint.ub]
|
|
700
|
+
ub = None if _is_cell_value_empty(ub) else float(ub)
|
|
701
|
+
|
|
702
|
+
# strict (optional)
|
|
703
|
+
strict = True
|
|
704
|
+
if ParseAsConstraint.strict in df.columns:
|
|
705
|
+
_strict = row[ParseAsConstraint.strict]
|
|
706
|
+
strict = True if _is_cell_value_empty(_strict) else bool(_strict) # bool or NaN
|
|
707
|
+
|
|
708
|
+
# using_fem (optional)
|
|
709
|
+
calc_before_solve = True
|
|
710
|
+
if ParseAsConstraint.calc_before_solve in df.columns:
|
|
711
|
+
_calc_before_solve = row[ParseAsConstraint.calc_before_solve]
|
|
712
|
+
calc_before_solve = True if _is_cell_value_empty(_calc_before_solve) else bool(
|
|
713
|
+
_calc_before_solve) # bool or NaN
|
|
714
|
+
|
|
715
|
+
if use:
|
|
716
|
+
opt.add_constraint(
|
|
717
|
+
name=name,
|
|
718
|
+
lower_bound=lb,
|
|
719
|
+
upper_bound=ub,
|
|
720
|
+
strict=strict,
|
|
721
|
+
fun=_ScapeGoatObjective(),
|
|
722
|
+
kwargs=dict(name=name),
|
|
723
|
+
using_fem=not calc_before_solve,
|
|
724
|
+
)
|
|
725
|
+
|
|
726
|
+
def objective_from_excel(self, _, name: str):
|
|
727
|
+
r = 1 + search_r(self.output_xlsm_path, self.output_sheet_name, name)
|
|
728
|
+
c = 1 + search_c(self.output_xlsm_path, self.output_sheet_name, ParseAsObjective.value)
|
|
729
|
+
v = self.sh_output.Cells(r, c).value
|
|
730
|
+
return float(v)
|
|
731
|
+
|
|
732
|
+
def constraint_from_excel(self, _, name: str):
|
|
733
|
+
r = 1 + search_r(self.constraint_xlsm_path, self.constraint_sheet_name, name)
|
|
734
|
+
c = 1 + search_c(self.constraint_xlsm_path, self.constraint_sheet_name, ParseAsConstraint.value)
|
|
735
|
+
v = self.sh_constraint.Cells(r, c).value
|
|
736
|
+
return float(v)
|
|
737
|
+
|
|
738
|
+
# ===== Workbook and WorkSheet =====
|
|
739
|
+
# unpicklable object を excel だけにするため
|
|
740
|
+
# これらのオブジェクトは動的に取得
|
|
741
|
+
def _get_wb(self, path) -> CDispatch:
|
|
742
|
+
for wb in self.excel.Workbooks:
|
|
743
|
+
if wb.Name == os.path.basename(path):
|
|
744
|
+
return wb
|
|
745
|
+
else:
|
|
746
|
+
raise WorkbookNotOpenedError(f'{path} is not opened.')
|
|
747
|
+
|
|
748
|
+
@staticmethod
|
|
749
|
+
def _get_sh(wb: CDispatch, name) -> CDispatch:
|
|
750
|
+
for sh in wb.WorkSheets:
|
|
751
|
+
if sh.Name == name:
|
|
752
|
+
return sh
|
|
753
|
+
else:
|
|
754
|
+
raise WorkSheetNotFoundError(
|
|
755
|
+
_(
|
|
756
|
+
en_message='{xla_file_path} not found. Please check the '
|
|
757
|
+
'"Enable Macros" command was executed.',
|
|
758
|
+
jp_message='{xla_file_path}が見つかりません。'
|
|
759
|
+
'"マクロを有効にする" command が実行'
|
|
760
|
+
'されたか確認してください。',
|
|
761
|
+
xla_file_path=wb.Name
|
|
762
|
+
)
|
|
763
|
+
)
|
|
764
|
+
|
|
765
|
+
@property
|
|
766
|
+
def wb_input(self) -> CDispatch:
|
|
767
|
+
return self._get_wb(self.input_xlsm_path)
|
|
768
|
+
|
|
769
|
+
@property
|
|
770
|
+
def sh_input(self) -> CDispatch:
|
|
771
|
+
return self._get_sh(self.wb_input, self.input_sheet_name)
|
|
772
|
+
|
|
773
|
+
@property
|
|
774
|
+
def wb_output(self) -> CDispatch:
|
|
775
|
+
return self._get_wb(self.output_xlsm_path)
|
|
776
|
+
|
|
777
|
+
@property
|
|
778
|
+
def sh_output(self) -> CDispatch:
|
|
779
|
+
return self._get_sh(self.wb_output, self.output_sheet_name)
|
|
780
|
+
|
|
781
|
+
@property
|
|
782
|
+
def wb_constraint(self) -> CDispatch:
|
|
783
|
+
return self._get_wb(self.constraint_xlsm_path)
|
|
784
|
+
|
|
785
|
+
@property
|
|
786
|
+
def sh_constraint(self) -> CDispatch:
|
|
787
|
+
return self._get_sh(self.wb_constraint, self.constraint_sheet_name)
|
|
788
|
+
|
|
789
|
+
@property
|
|
790
|
+
def wb_procedure(self) -> CDispatch:
|
|
791
|
+
return self._get_wb(self.procedure_xlsm_path)
|
|
792
|
+
|
|
793
|
+
@property
|
|
794
|
+
def wb_setup(self) -> CDispatch:
|
|
795
|
+
return self._get_wb(self.setup_xlsm_path)
|
|
796
|
+
|
|
797
|
+
@property
|
|
798
|
+
def wb_teardown(self) -> CDispatch:
|
|
799
|
+
return self._get_wb(self.teardown_xlsm_path)
|
|
800
|
+
|
|
801
|
+
# ===== update =====
|
|
802
|
+
def update_parameter(self, x: dict[str, SupportedVariableTypes]) -> None:
|
|
803
|
+
|
|
804
|
+
COMInterface.update_parameter(self, x)
|
|
805
|
+
|
|
806
|
+
# excel シートの変数更新
|
|
807
|
+
if self.use_named_range:
|
|
808
|
+
for key, value in self.current_prm_values.items():
|
|
809
|
+
try:
|
|
810
|
+
self.sh_input.Range(key).value = value
|
|
811
|
+
except com_error:
|
|
812
|
+
logger.warning(
|
|
813
|
+
_(
|
|
814
|
+
en_message='The cell address specification by named range is failed. '
|
|
815
|
+
'The process changes the specification method to table based.',
|
|
816
|
+
jp_message='名前範囲によるセルアドレス指定に失敗しました。'
|
|
817
|
+
'処理は指定方法をテーブルに変更します。',
|
|
818
|
+
)
|
|
819
|
+
)
|
|
820
|
+
self.use_named_range = False
|
|
821
|
+
break
|
|
822
|
+
|
|
823
|
+
if not self.use_named_range: # else にしないこと
|
|
824
|
+
for name, value in self.current_prm_values.items():
|
|
825
|
+
r = 1 + search_r(self.input_xlsm_path, self.input_sheet_name, name)
|
|
826
|
+
c = 1 + search_c(self.input_xlsm_path, self.input_sheet_name, ParseAsParameter.value)
|
|
827
|
+
self.sh_input.Cells(r, c).value = value
|
|
828
|
+
|
|
829
|
+
# 再計算
|
|
830
|
+
self.excel.CalculateFull()
|
|
831
|
+
|
|
832
|
+
def update(self) -> None:
|
|
833
|
+
|
|
834
|
+
if self.procedure_name is None:
|
|
835
|
+
return
|
|
836
|
+
|
|
837
|
+
# マクロ実行
|
|
838
|
+
try:
|
|
839
|
+
self.wb_procedure.Activate()
|
|
840
|
+
sleep(0.1)
|
|
841
|
+
with watch_excel_macro_error(self.excel, timeout=self.procedure_timeout):
|
|
842
|
+
self.excel.Run(
|
|
843
|
+
f'{self.procedure_name}',
|
|
844
|
+
*self.procedure_args
|
|
845
|
+
)
|
|
846
|
+
|
|
847
|
+
# 再計算
|
|
848
|
+
self.excel.CalculateFull()
|
|
849
|
+
|
|
850
|
+
except com_error as e:
|
|
851
|
+
raise SolveError(
|
|
852
|
+
# 変換後(あなたの出力)
|
|
853
|
+
_(
|
|
854
|
+
en_message='Failed to run macro {procedure_name}. '
|
|
855
|
+
'The original message is: {exception}',
|
|
856
|
+
jp_message='マクロ {procedure_name} の実行に失敗しました。 '
|
|
857
|
+
'エラーメッセージ: {exception}',
|
|
858
|
+
procedure_name=self.procedure_name,
|
|
859
|
+
exception=e
|
|
860
|
+
)
|
|
861
|
+
)
|
|
862
|
+
|
|
863
|
+
# ===== close =====
|
|
864
|
+
def _close_workbooks(self):
|
|
865
|
+
# workbook を閉じる
|
|
866
|
+
with watch_excel_macro_error(self.excel, timeout=10, restore_book=False):
|
|
867
|
+
self.wb_input.Close(_SaveChanges := False)
|
|
868
|
+
|
|
869
|
+
def close_wb_if_needed(attrib_name_):
|
|
870
|
+
try:
|
|
871
|
+
# self.wb_output などとすると
|
|
872
|
+
# 関数呼び出しの時点でエラーになる
|
|
873
|
+
wb = getattr(self, attrib_name_)
|
|
874
|
+
except WorkbookNotOpenedError:
|
|
875
|
+
pass
|
|
876
|
+
else:
|
|
877
|
+
with watch_excel_macro_error(self.excel, timeout=10, restore_book=False):
|
|
878
|
+
wb.Close(False)
|
|
879
|
+
|
|
880
|
+
close_wb_if_needed('wb_output')
|
|
881
|
+
close_wb_if_needed('wb_constraint')
|
|
882
|
+
close_wb_if_needed('wb_procedure')
|
|
883
|
+
close_wb_if_needed('wb_setup')
|
|
884
|
+
close_wb_if_needed('wb_teardown')
|
|
885
|
+
|
|
886
|
+
def close(self):
|
|
887
|
+
|
|
888
|
+
# 無駄に不具合に遭う可能性があるので
|
|
889
|
+
# 参照設定は解除しない
|
|
890
|
+
|
|
891
|
+
if not hasattr(self, 'excel'):
|
|
892
|
+
return
|
|
893
|
+
|
|
894
|
+
if self.excel is None:
|
|
895
|
+
return
|
|
896
|
+
|
|
897
|
+
# 終了処理を必要なら実施する
|
|
898
|
+
if self.teardown_procedure_name is not None:
|
|
899
|
+
|
|
900
|
+
logger.info(_(
|
|
901
|
+
en_message='{procedure_kind} procedure {procedure_name} is running...',
|
|
902
|
+
jp_message='{procedure_kind} プロシージャ {procedure_name} が実行中...',
|
|
903
|
+
procedure_kind='Teardown',
|
|
904
|
+
procedure_name=self.teardown_procedure_name
|
|
905
|
+
))
|
|
906
|
+
|
|
907
|
+
with Lock('excel_teardown_procedure'):
|
|
908
|
+
try:
|
|
909
|
+
self.wb_teardown.Activate()
|
|
910
|
+
sleep(0.1)
|
|
911
|
+
with watch_excel_macro_error(self.excel, timeout=self.procedure_timeout, restore_book=False):
|
|
912
|
+
self.excel.Run(
|
|
913
|
+
f'{self.teardown_procedure_name}',
|
|
914
|
+
*self.teardown_procedure_args
|
|
915
|
+
)
|
|
916
|
+
|
|
917
|
+
# 再計算
|
|
918
|
+
self.excel.CalculateFull()
|
|
919
|
+
|
|
920
|
+
except com_error as e:
|
|
921
|
+
raise RuntimeError(
|
|
922
|
+
_(
|
|
923
|
+
en_message='Failed to run macro {procedure_name}. '
|
|
924
|
+
'The original message is: {exception}',
|
|
925
|
+
jp_message='マクロ {procedure_name} の実行に失敗しました。 '
|
|
926
|
+
'エラーメッセージ: {exception}',
|
|
927
|
+
procedure_name=self.teardown_procedure_name,
|
|
928
|
+
exception=e
|
|
929
|
+
)
|
|
930
|
+
)
|
|
931
|
+
|
|
932
|
+
# excel プロセスを終了する
|
|
933
|
+
if self.terminate_excel_when_quit:
|
|
934
|
+
|
|
935
|
+
logger.info(_(
|
|
936
|
+
en_message='Terminating Excel process...',
|
|
937
|
+
jp_message='Excel プロセスを終了しています...',
|
|
938
|
+
))
|
|
939
|
+
|
|
940
|
+
already_terminated = not hasattr(self, 'excel')
|
|
941
|
+
if already_terminated:
|
|
942
|
+
return
|
|
943
|
+
|
|
944
|
+
# ワークブックを閉じる
|
|
945
|
+
self._close_workbooks()
|
|
946
|
+
|
|
947
|
+
# excel の終了
|
|
948
|
+
with watch_excel_macro_error(self.excel, timeout=10, restore_book=False):
|
|
949
|
+
self.excel.Quit()
|
|
950
|
+
del self.excel
|
|
951
|
+
|
|
952
|
+
# ここで Excel のプロセスが残らず落ちる
|
|
953
|
+
gc.collect()
|
|
954
|
+
logger.info(_(
|
|
955
|
+
en_message='Excel process is terminated.',
|
|
956
|
+
jp_message='Excel プロセスは終了しました。',
|
|
957
|
+
))
|
|
958
|
+
|
|
959
|
+
if self._with_femtet_autosave_setting:
|
|
960
|
+
logger.info(_(
|
|
961
|
+
en_message='Restore Femtet setting of autosave.',
|
|
962
|
+
jp_message='Femtet の自動保存設定を復元しています。',
|
|
963
|
+
))
|
|
964
|
+
_set_autosave_enabled(self._femtet_autosave_buffer)
|
|
965
|
+
|
|
966
|
+
# そうでない場合でもブックは閉じる
|
|
967
|
+
else:
|
|
968
|
+
self._close_workbooks()
|
|
969
|
+
|
|
970
|
+
|
|
971
|
+
# main thread で作成した excel への参照を含む関数を
|
|
972
|
+
# 直接 thread や process に渡すと機能しない
|
|
973
|
+
class _ScapeGoatObjective:
|
|
974
|
+
|
|
975
|
+
# for type hint
|
|
976
|
+
def __call__(self) -> float:
|
|
977
|
+
pass
|
|
978
|
+
|
|
979
|
+
@property
|
|
980
|
+
def __globals__(self):
|
|
981
|
+
return dict()
|
|
982
|
+
|
|
983
|
+
|
|
984
|
+
def _is_same_path(p1, p2):
|
|
985
|
+
_p1 = os.path.abspath(p1).lower()
|
|
986
|
+
_p2 = os.path.abspath(p2).lower()
|
|
987
|
+
return _p1 == _p2
|
|
988
|
+
|
|
989
|
+
|
|
990
|
+
def _is_cell_value_empty(cell_value):
|
|
991
|
+
if isinstance(cell_value, str):
|
|
992
|
+
return cell_value == ''
|
|
993
|
+
elif isinstance(cell_value, int) \
|
|
994
|
+
or isinstance(cell_value, float):
|
|
995
|
+
return np.isnan(cell_value)
|
|
996
|
+
elif cell_value is None:
|
|
997
|
+
return True
|
|
998
|
+
else:
|
|
999
|
+
return False
|