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.

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 +29 -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 +94 -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 +608 -0
  31. pyfemtet/opt/history/__init__.py +11 -0
  32. pyfemtet/opt/history/_history.py +1404 -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 +999 -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} +505 -349
  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 +122 -0
  50. pyfemtet/opt/interface/_solidworks_interface/__init__.py +5 -0
  51. pyfemtet/opt/interface/_solidworks_interface/solidworks_interface.py +206 -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 +885 -0
  62. pyfemtet/opt/optimizer/optuna_optimizer/__init__.py +9 -0
  63. pyfemtet/opt/optimizer/optuna_optimizer/_optuna_attribute.py +73 -0
  64. pyfemtet/opt/optimizer/optuna_optimizer/_optuna_optimizer.py +678 -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 +364 -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.0b0.dist-info}/METADATA +23 -24
  151. pyfemtet-1.0.0b0.dist-info/RECORD +172 -0
  152. pyfemtet-1.0.0b0.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.0b0.dist-info}/LICENSE +0 -0
  271. {pyfemtet-0.9.5.dist-info → pyfemtet-1.0.0b0.dist-info}/LICENSE_THIRD_PARTY.txt +0 -0
  272. {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