pyfemtet 0.9.5__py3-none-any.whl → 1.0.0__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.

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