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,796 @@
1
+ from __future__ import annotations
2
+
3
+ import gc
4
+ import os
5
+ import inspect
6
+ import tempfile
7
+ import warnings
8
+ from time import sleep
9
+ from contextlib import suppress, nullcontext
10
+
11
+ import numpy as np
12
+
13
+ import optuna
14
+ from optuna.samplers import TPESampler
15
+ from optuna.study import MaxTrialsCallback
16
+ from optuna_integration.dask import DaskStorage
17
+
18
+ from pyfemtet._i18n import _
19
+ from pyfemtet.opt.history import *
20
+ from pyfemtet.opt.interface import *
21
+ from pyfemtet.opt.exceptions import *
22
+ from pyfemtet.opt.problem.variable_manager import *
23
+ from pyfemtet._util.dask_util import *
24
+ from pyfemtet._util.closing import closing
25
+ from pyfemtet.logger import get_optuna_logger, remove_all_output, get_module_logger
26
+
27
+ from pyfemtet.opt.optimizer._base_optimizer import *
28
+ from pyfemtet.opt.optimizer.optuna_optimizer._optuna_attribute import OptunaAttribute
29
+ from pyfemtet.opt.optimizer.optuna_optimizer._pof_botorch.pof_botorch_sampler import PoFBoTorchSampler
30
+ from pyfemtet.opt.worker_status import WorkerStatus
31
+
32
+ logger = get_module_logger('opt.optimizer', False)
33
+
34
+ remove_all_output(get_optuna_logger())
35
+
36
+ warnings.filterwarnings('ignore', 'set_metric_names', optuna.exceptions.ExperimentalWarning)
37
+ warnings.filterwarnings('ignore', 'Argument ``constraints_func`` is an experimental feature.',
38
+ optuna.exceptions.ExperimentalWarning)
39
+
40
+
41
+ class OptunaOptimizer(AbstractOptimizer):
42
+ """
43
+ An optimizer class utilizing Optuna for hyperparameter optimization.
44
+
45
+ This class provides an interface to conduct optimization studies using Optuna.
46
+ It manages the study lifecycle, sampler configuration, and trial execution.
47
+
48
+ Attributes:
49
+ study_name (str): Name of the Optuna study.
50
+ storage (str | optuna.storages.BaseStorage): Storage URL or object for the Optuna study.
51
+ storage_path (str): Path to the Optuna study storage.
52
+ current_trial (optuna.trial.Trial | None): The current Optuna trial being evaluated.
53
+ sampler_class (type[optuna.samplers.BaseSampler]): The class of the Optuna sampler to use.
54
+ sampler_kwargs (dict): Keyword arguments to initialize the sampler.
55
+ n_trials (int | None): Number of trials to run in the study.
56
+ timeout (float | None): Maximum time allowed for the optimization.
57
+ callbacks (list): List of callback functions to invoke during optimization.
58
+
59
+ Args:
60
+ sampler_class (type[optuna.samplers.BaseSampler], optional): The sampler class for suggesting parameter values. Defaults to TPESampler if None.
61
+ sampler_kwargs (dict[str, ...], optional): Dictionary of keyword arguments for the sampler. Defaults to an empty dictionary.
62
+
63
+ Raises:
64
+ None
65
+
66
+ Examples:
67
+ >>> optimizer = OptunaOptimizer()
68
+ >>> optimizer.n_trials = 100
69
+ >>> optimizer.timeout = 600
70
+ >>> # Further configuration and usage...
71
+ """
72
+
73
+ # system
74
+ study_name = 'pyfemtet-study'
75
+ storage: str | optuna.storages.BaseStorage
76
+ storage_path: str
77
+ current_trial: optuna.trial.Trial | None
78
+
79
+ # settings
80
+ # sampler: optuna.samplers.BaseSampler | None = None # reseed_rng が seed 指定できないため
81
+ sampler_class: type[optuna.samplers.BaseSampler]
82
+ sampler_kwargs: dict
83
+ n_trials: int | None
84
+ timeout: float | None
85
+ callbacks: list
86
+
87
+ def __init__(
88
+ self,
89
+ sampler_class: type[optuna.samplers.BaseSampler] = None,
90
+ sampler_kwargs: dict[str, ...] = None,
91
+ ):
92
+ super().__init__()
93
+ self.sampler_kwargs = sampler_kwargs or {}
94
+ self.sampler_class = sampler_class or TPESampler
95
+ self.n_trials: int | None = None
96
+ self.timeout: float | None = None
97
+ self.callbacks = []
98
+
99
+ # ===== method checker =====
100
+ # noinspection PyMethodOverriding
101
+ def add_parameter(
102
+ self,
103
+ name: str,
104
+ initial_value: float,
105
+ lower_bound: float,
106
+ upper_bound: float,
107
+ step: float | None = None,
108
+ properties: dict[str, ...] | None = None,
109
+ *,
110
+ pass_to_fem: bool = True,
111
+ fix: bool = False,
112
+ ) -> None:
113
+ AbstractOptimizer.add_parameter(self, name, initial_value, lower_bound, upper_bound, step, properties,
114
+ pass_to_fem=pass_to_fem, fix=fix)
115
+
116
+ # noinspection PyMethodOverriding
117
+ def add_categorical_parameter(
118
+ self,
119
+ name: str,
120
+ initial_value: str,
121
+ choices: list[str],
122
+ properties: dict[str, ...] | None = None,
123
+ *,
124
+ pass_to_fem: bool = True,
125
+ fix: bool = False,
126
+ ) -> None:
127
+ AbstractOptimizer.add_categorical_parameter(self, name, initial_value, choices, properties,
128
+ pass_to_fem=pass_to_fem, fix=fix)
129
+
130
+ class _SolveSet(AbstractOptimizer._SolveSet):
131
+ opt: OptunaOptimizer
132
+ optuna_attr: OptunaAttribute
133
+
134
+ def _preprocess(self):
135
+ # prepare attribute
136
+ self.optuna_attr = OptunaAttribute(self.opt_)
137
+
138
+ def _common(self, e):
139
+ # if (hidden) constraint violation, set trial attribute
140
+ self.optuna_attr.pf_state = TrialState.get_corresponding_state_from_exception(e)
141
+ self.optuna_attr.v_values = self.opt._create_infeasible_constraints(self.opt_)
142
+
143
+ def _hard_constraint_handling(self, e: HardConstraintViolation):
144
+ self._common(e)
145
+
146
+ def _hidden_constraint_handling(self, e: _HiddenConstraintViolation):
147
+ self._common(e)
148
+
149
+ def _skip_handling(self, e: SkipSolve):
150
+ self.optuna_attr.pf_state = TrialState.skipped
151
+
152
+ def _if_succeeded(self, f_return: _FReturnValue):
153
+
154
+ y, dict_y_internal, c, record = f_return
155
+
156
+ # convert constraint to **sorted 1-d array** violation
157
+ assert len(c) == len(self.opt_.constraints)
158
+ v = {}
159
+ for cns_name, cns in self.opt_.constraints.items():
160
+ # This is {lower or upper: violation_value} dict
161
+ violation: dict[str, float] = c[cns_name].calc_violation()
162
+ for l_or_u, violation_value in violation.items():
163
+ key_ = cns_name + '_' + l_or_u
164
+ v.update({key_: violation_value})
165
+
166
+ # register results
167
+ self.optuna_attr.v_values = tuple(v.values())
168
+ self.optuna_attr.y_values = tuple(dict_y_internal.values())
169
+ self.optuna_attr.pf_state = record.state
170
+
171
+ def _postprocess(self):
172
+ # update trial attribute
173
+ self.optuna_attr.set_user_attr_to_trial(self.opt.current_trial)
174
+
175
+ def _create_infeasible_constraints(self, opt_: AbstractOptimizer = None) -> tuple:
176
+ opt_ = opt_ if opt_ is not None else self
177
+ count = 0
178
+ for name, cns in opt_.constraints.items():
179
+ if cns.lower_bound is not None:
180
+ count += 1
181
+ if cns.upper_bound is not None:
182
+ count += 1
183
+ return tuple(1e9 * np.ones(count, dtype=np.float64))
184
+
185
+ def _constraint(self, trial: optuna.trial.FrozenTrial):
186
+ main_key = OptunaAttribute(self).key
187
+ user_attribute: OptunaAttribute.AttributeStructure = trial.user_attrs[main_key]
188
+ return user_attribute['violation_values']
189
+
190
+ def _objective(self, trial: optuna.trial.Trial):
191
+
192
+ self.current_trial = trial
193
+
194
+ with self._logging():
195
+
196
+ vm = self.variable_manager
197
+
198
+ # check interruption
199
+ self._check_and_raise_interruption()
200
+
201
+ # parameter suggestion
202
+ params = vm.get_variables(filter='parameter')
203
+ for name, prm in params.items():
204
+
205
+ if prm.properties.get('fix', False): # default is False
206
+ continue
207
+
208
+ if isinstance(prm, NumericParameter):
209
+ prm.value = trial.suggest_float(
210
+ name,
211
+ prm.lower_bound,
212
+ prm.upper_bound,
213
+ step=prm.step,
214
+ log=prm.properties.get('log', __default := False),
215
+ )
216
+ elif isinstance(prm, CategoricalParameter):
217
+ prm.value = trial.suggest_categorical(
218
+ name, prm.choices
219
+ )
220
+ else:
221
+ raise NotImplementedError
222
+
223
+ # evaluate expressions
224
+ vm.eval_expressions()
225
+
226
+ # check interruption
227
+ self._check_and_raise_interruption()
228
+
229
+ # construct TrialInput
230
+ x = vm.get_variables(filter='parameter')
231
+ x_pass_to_fem: dict[str, SupportedVariableTypes] = vm.get_variables(filter='pass_to_fem', format='dict')
232
+
233
+ # prepare solve
234
+ solve_set = self._get_solve_set()
235
+
236
+ # process main fidelity model
237
+ f_return = solve_set.solve(x, x_pass_to_fem)
238
+ if f_return is None:
239
+ y_internal: None = None
240
+ else:
241
+ y_internal: tuple[float] = tuple(f_return[1].values()) # type: ignore
242
+
243
+ # process sub_fidelity_models
244
+ for sub_fidelity_name, sub_opt in self.sub_fidelity_models.items():
245
+ # _SolveSet に特殊な初期化を入れていないので
246
+ # sub fidelity でも初期化せず使用可能
247
+ solve_set.solve(x, x_pass_to_fem, sub_opt)
248
+
249
+ # check interruption
250
+ self._check_and_raise_interruption()
251
+
252
+ # clear trial
253
+ self.current_trial = None
254
+
255
+ # To avoid trial FAILED with hard constraint
256
+ # violation, check pf_state and raise TrialPruned.
257
+ main_key = OptunaAttribute(self).key
258
+ user_attribute: OptunaAttribute.AttributeStructure = trial.user_attrs[main_key]
259
+ state: TrialState = user_attribute['pf_state']
260
+ if state in [
261
+ TrialState.hard_constraint_violation,
262
+ TrialState.model_error,
263
+ TrialState.mesh_error,
264
+ TrialState.solve_error,
265
+ TrialState.post_error,
266
+ ]:
267
+ raise optuna.TrialPruned
268
+
269
+ # if main solve skipped, y_internal is empty.
270
+ # this should be processed as FAIL.
271
+ elif state == TrialState.skipped:
272
+ return None
273
+
274
+ return y_internal
275
+
276
+ def _get_callback(self, n_trials: int):
277
+
278
+ # restart である場合、追加 N 回と見做す
279
+ if self.history.is_restart:
280
+ df = self.history.get_df(equality_filters=MAIN_FILTER)
281
+ n_existing_succeeded_trials = len(df[df['state'] == TrialState.succeeded])
282
+ n_trials = n_trials + n_existing_succeeded_trials
283
+
284
+ return MaxTrialsCallback(n_trials, states=(optuna.trial.TrialState.COMPLETE,))
285
+
286
+ def _setup_before_parallel(self):
287
+
288
+ if self._done_setup_before_parallel:
289
+ return
290
+
291
+ AbstractOptimizer._setup_before_parallel(self) # set flag inside this
292
+
293
+ # set default values
294
+ self.sampler_class = self.sampler_class or optuna.samplers.TPESampler
295
+ self.sampler_kwargs = self.sampler_kwargs or {}
296
+
297
+ # remove automatically-given arguments
298
+ if 'seed' in self.sampler_kwargs:
299
+ warnings.warn('sampler_kwargs `seed` は'
300
+ 'Optimizer.set_random_seed() で'
301
+ '与えてください。引数は無視されます。')
302
+ self.sampler_kwargs.pop('seed')
303
+ if 'constraints_func' in self.sampler_kwargs:
304
+ warnings.warn('sampler_kwargs `constraints_func` は'
305
+ 'pyfemtet.opt の内部で自動的に与えられます。'
306
+ '引数は無視されます。')
307
+ self.sampler_kwargs.pop('constraints_func')
308
+
309
+ # create storage path
310
+ self.storage_path = self.history.path.removesuffix('.csv') + '.db'
311
+
312
+ # file check
313
+ if self.history.is_restart:
314
+ # check db file existing
315
+ if not os.path.exists(self.storage_path):
316
+ raise FileNotFoundError(self.storage_path)
317
+ else:
318
+ # certify no db file
319
+ if os.path.isfile(self.storage_path):
320
+ os.remove(self.storage_path)
321
+
322
+ # if TPESampler and re-starting,
323
+ # create temporary study to avoid error
324
+ # with many pruned trials.
325
+ if issubclass(self.sampler_class, optuna.samplers.TPESampler) \
326
+ and self.history.is_restart:
327
+ # get unique tmp file
328
+ tmp_storage_path = tempfile.mktemp(suffix='.db')
329
+ self._existing_storage_path = self.storage_path
330
+ self.storage_path = tmp_storage_path
331
+
332
+ # load existing study
333
+ existing_study = optuna.load_study(
334
+ study_name=self.study_name,
335
+ storage=f'sqlite:///{self._existing_storage_path}',
336
+ )
337
+
338
+ # create new study
339
+ tmp_study = optuna.create_study(
340
+ study_name=self.study_name,
341
+ storage=f'sqlite:///{self.storage_path}',
342
+ load_if_exists=True,
343
+ directions=['minimize'] * len(self.objectives),
344
+ )
345
+
346
+ # Copy COMPLETE trials to temporary study.
347
+ existing_trials = existing_study.get_trials(states=(optuna.trial.TrialState.COMPLETE,))
348
+ tmp_study.add_trials(existing_trials)
349
+
350
+ # setup storage
351
+ client = get_client()
352
+ if client is None:
353
+ self.storage = optuna.storages.get_storage(f'sqlite:///{self.storage_path}')
354
+ else:
355
+ self.storage = DaskStorage(
356
+ f'sqlite:///{self.storage_path}'
357
+ )
358
+
359
+ # if new study, create it.
360
+ if not self.history.is_restart:
361
+ # create study
362
+ study = optuna.create_study(
363
+ study_name=self.study_name,
364
+ storage=self.storage,
365
+ load_if_exists=True,
366
+ directions=['minimize'] * len(self.objectives),
367
+ )
368
+
369
+ # set objective names
370
+ study.set_metric_names(list(self.objectives.keys()))
371
+
372
+ # initial trial
373
+ params = self.variable_manager.get_variables(format='dict', filter='parameter')
374
+ study.enqueue_trial(params, user_attrs={"message": "Initial values"})
375
+
376
+ def _setup_after_parallel(self):
377
+ # reseed
378
+ worker = get_worker()
379
+ if worker is not None:
380
+ # self.sampler.reseed_rng() # サブプロセスのランダム化が固定されない
381
+ idx = self._worker_index
382
+ assert isinstance(idx, int)
383
+ if self.seed is not None:
384
+ self.seed += idx
385
+
386
+ def _is_tpe_addressing(self):
387
+ out = False
388
+ if hasattr(self, '_existing_storage_path'):
389
+ if self._existing_storage_path is not None:
390
+ assert os.path.isfile(self._existing_storage_path)
391
+ out = True
392
+ return out
393
+
394
+ def _removing_tmp_db_if_needed(self):
395
+
396
+ if not self._is_tpe_addressing():
397
+ return nullcontext()
398
+
399
+ # noinspection PyMethodParameters
400
+ class RemovingTempDB:
401
+ def __enter__(self_):
402
+ pass
403
+
404
+ def __exit__(self_, exc_type, exc_val, exc_tb):
405
+
406
+ # clean up temporary file
407
+ if isinstance(self.storage, optuna.storages._CachedStorage):
408
+ rdb_storage = self.storage._backend
409
+ elif isinstance(self.storage, optuna.storages.RDBStorage):
410
+ rdb_storage = self.storage
411
+ elif isinstance(self.storage, DaskStorage):
412
+ base_storage = self.storage.get_base_storage()
413
+ assert isinstance(base_storage, optuna.storages._CachedStorage)
414
+ rdb_storage = base_storage._backend
415
+ else:
416
+ raise NotImplementedError(f'{type(self.storage)=}')
417
+
418
+ assert isinstance(rdb_storage, optuna.storages.RDBStorage)
419
+
420
+ client = get_client()
421
+
422
+ # 最後のプロセスにしか消せないので、
423
+ # 各 worker は dispose だけは行い、
424
+ # 削除は失敗しても気にしないことにする
425
+
426
+ if client is None:
427
+ # 通常 dispose
428
+ rdb_storage.engine.dispose()
429
+
430
+ # run_on_scheduler での dispose
431
+ else:
432
+
433
+ # 他の worker を待つ
434
+ while True:
435
+ if all([ws.value >= WorkerStatus.finishing for ws in self.worker_status_list]):
436
+ break
437
+ sleep(1)
438
+
439
+ # 通常 dispose
440
+ rdb_storage.engine.dispose()
441
+
442
+ def dispose_(dask_scheduler):
443
+ assert isinstance(self.storage, DaskStorage)
444
+ name_ = self.storage.name
445
+ ext = dask_scheduler.extensions["optuna"]
446
+ base_storage_ = ext.storages[name_]
447
+ rdb_storage_ = base_storage_._backend
448
+ rdb_storage_.engine.dispose()
449
+
450
+ client.run_on_scheduler(dispose_)
451
+ gc.collect()
452
+
453
+ # try remove
454
+ if os.path.exists(self.storage_path):
455
+ try:
456
+ os.remove(self.storage_path)
457
+ except PermissionError:
458
+ logger.debug(f'パーミッションエラー。{self.storage_path} の削除処理をスキップします。')
459
+ else:
460
+ logger.debug(f'{self.storage_path} の削除に成功しました。')
461
+
462
+ self.storage_path = self._existing_storage_path
463
+
464
+ return RemovingTempDB()
465
+
466
+ def run(self):
467
+
468
+ # ===== finalize =====
469
+ self._finalize()
470
+
471
+ # ===== construct sampler =====
472
+
473
+ # automatically-given arguments
474
+ if len(self.constraints) > 0:
475
+ self.sampler_kwargs.update(
476
+ constraints_func=self._constraint
477
+ )
478
+ if self.seed is not None:
479
+ self.sampler_kwargs.update(
480
+ seed=self.seed
481
+ )
482
+
483
+ actual_sampler_kwargs = dict()
484
+ arguments = inspect.signature(self.sampler_class.__init__).parameters
485
+ for k, v in self.sampler_kwargs.items():
486
+
487
+ # the key is valid, pass to sampler
488
+ if k in arguments.keys():
489
+ actual_sampler_kwargs.update({k: v})
490
+
491
+ # if not automatically-given arguments,
492
+ # show warning
493
+ elif k not in ('seed', 'constraints_func'):
494
+ logger.warning(_(
495
+ en_message='The given argument {key} is not '
496
+ 'included in ones of {sampler_name}. '
497
+ '{key} is ignored.',
498
+ jp_message='{key} は {sampler_name} の'
499
+ '有効な引数ではないので'
500
+ '無視されます。',
501
+ key=k,
502
+ sampler_name=self.sampler_class.__name__,
503
+ ))
504
+
505
+ # else, ignore it
506
+ else:
507
+ pass
508
+
509
+ # noinspection PyArgumentList
510
+ sampler = self.sampler_class(**actual_sampler_kwargs)
511
+
512
+ # if PoFBoTorchSampler, set opt
513
+ if isinstance(sampler, PoFBoTorchSampler):
514
+ sampler.pyfemtet_optimizer = self # FIXME: multi-fidelity に対応できない?
515
+
516
+ # ===== load study and run =====
517
+
518
+ # after quit FEM, try to remove tmp db
519
+ with self._removing_tmp_db_if_needed():
520
+
521
+ # quit FEM even if abnormal termination
522
+ with closing(self.fem):
523
+
524
+ # load study creating in setup_before_parallel()
525
+ # located on dask scheduler
526
+ study = optuna.load_study(
527
+ study_name=self.study_name,
528
+ storage=self.storage,
529
+ sampler=sampler,
530
+ )
531
+
532
+ # if tpe_addressing, load main study
533
+ if self._is_tpe_addressing():
534
+ # load it
535
+ existing_study = optuna.load_study(
536
+ study_name=self.study_name,
537
+ storage=f'sqlite:///{self._existing_storage_path}',
538
+ )
539
+
540
+ # and add callback to copy-back
541
+ # from processing study to existing one.
542
+ def copy_back(_, trial):
543
+ existing_study.add_trial(trial)
544
+
545
+ self.callbacks.append(copy_back)
546
+
547
+ # callback
548
+ if self.n_trials is not None:
549
+ self.callbacks.append(self._get_callback(self.n_trials))
550
+
551
+ # run
552
+ with self._setting_status(), suppress(InterruptOptimization):
553
+ study.optimize(
554
+ self._objective,
555
+ timeout=self.timeout,
556
+ callbacks=self.callbacks,
557
+ )
558
+
559
+
560
+ def debug_1():
561
+ # from pyfemtet.opt.optimizer.optuna_optimizer.pof_botorch.pof_botorch_sampler import
562
+ # sampler = PoFBoTorchSampler(
563
+ # n_startup_trials=5,
564
+ # seed=42,
565
+ # constraints_func=self._constraint,
566
+ # pof_config=PoFConfig(
567
+ # # consider_pof=False,
568
+ # # feasibility_cdf_threshold='mean',
569
+ # ),
570
+ # partial_optimize_acqf_kwargs=PartialOptimizeACQFConfig(
571
+ # # gen_candidates='scipy',
572
+ # timeout_sec=5.,
573
+ # # method='SLSQP' # 'COBYLA, COBYQA, SLSQP or trust-constr
574
+ # tol=0.1,
575
+ # # scipy_minimize_kwargs=dict(),
576
+ # ),
577
+ # )
578
+ # from optuna_integration import BoTorchSampler
579
+ # sampler = BoTorchSampler(n_startup_trials=5)
580
+
581
+ os.chdir(os.path.dirname(__file__))
582
+
583
+ def _parabola(_fem: AbstractFEMInterface, _opt: AbstractOptimizer) -> float:
584
+ d = _opt.get_variables()
585
+ x1 = d['x1']
586
+ x2 = d['x2']
587
+ # if _cns(_fem, _opt) < 0:
588
+ # raise PostProcessError
589
+ return x1 ** 2 + x2 ** 2
590
+
591
+ def _parabola2(_fem: AbstractFEMInterface, _opt: AbstractOptimizer) -> float:
592
+ x = _opt.get_variables('values')
593
+ return ((x - 0.1) ** 2).sum()
594
+
595
+ def _cns(_fem: AbstractFEMInterface, _opt: AbstractOptimizer) -> float:
596
+ x = _opt.get_variables('values')
597
+ return x[0]
598
+
599
+ _fem = NoFEM()
600
+ _opt = OptunaOptimizer()
601
+ _opt.fem = _fem
602
+
603
+ # _opt.sampler = optuna.samplers.RandomSampler(seed=42)
604
+ _opt.seed = 42
605
+ _opt.sampler_class = optuna.samplers.TPESampler
606
+ # _opt.sampler_class = optuna.samplers.RandomSampler
607
+ _opt.sampler_kwargs = dict(
608
+ n_startup_trials=5,
609
+ )
610
+ _opt.n_trials = 10
611
+
612
+ _opt.add_parameter('x1', 1, -1, 1, step=0.1)
613
+ _opt.add_parameter('x2', 1, -1, 1, step=0.1)
614
+ _opt.add_categorical_parameter('x3', 'a', choices=['a', 'b', 'c'])
615
+ # _opt.add_constraint('cns', _cns, lower_bound=-0.9, args=(_opt,))
616
+ _opt.add_objective('obj1', _parabola, args=(_opt,))
617
+ # _opt.add_objective('obj2', _parabola2, args=(_opt,))
618
+
619
+ # # ===== sub-fidelity =====
620
+ # __fem = NoFEM()
621
+ # __opt = SubFidelityModel()
622
+ # __opt.fem = __fem
623
+ # __opt.add_objective('obj1', _parabola, args=(__opt,))
624
+ # # __opt.add_objective('obj2', _parabola2, args=(__opt,))
625
+ #
626
+ # _opt.add_sub_fidelity_model(name='low-fidelity', sub_fidelity_model=__opt, fidelity=0.5)
627
+ #
628
+ # def _solve_condition(_history: History):
629
+ #
630
+ # sub_fidelity_df = _history.get_df(
631
+ # {'sub_fidelity_name': 'low-fidelity'}
632
+ # )
633
+ # idx = sub_fidelity_df['state'] == TrialState.succeeded
634
+ # pdf = sub_fidelity_df[idx]
635
+ #
636
+ # return len(pdf) % 5 == 0
637
+ #
638
+ # _opt.set_solve_condition(_solve_condition)
639
+
640
+ # _opt.history.path = 'restart-test.csv'
641
+ _opt.run()
642
+
643
+ # import plotly.express as px
644
+ # _df = _opt.history.get_df()
645
+ # px.scatter_3d(_df, x='x1', y='x2', z='obj', color='fidelity', opacity=0.5).show()
646
+
647
+ _opt.history.save()
648
+
649
+
650
+ def debug_1s():
651
+ # from pyfemtet.opt.optimizer.optuna_optimizer.pof_botorch.pof_botorch_sampler import
652
+ # sampler = PoFBoTorchSampler(
653
+ # n_startup_trials=5,
654
+ # seed=42,
655
+ # constraints_func=self._constraint,
656
+ # pof_config=PoFConfig(
657
+ # # consider_pof=False,
658
+ # # feasibility_cdf_threshold='mean',
659
+ # ),
660
+ # partial_optimize_acqf_kwargs=PartialOptimizeACQFConfig(
661
+ # # gen_candidates='scipy',
662
+ # timeout_sec=5.,
663
+ # # method='SLSQP' # 'COBYLA, COBYQA, SLSQP or trust-constr
664
+ # tol=0.1,
665
+ # # scipy_minimize_kwargs=dict(),
666
+ # ),
667
+ # )
668
+ # from optuna_integration import BoTorchSampler
669
+ # sampler = BoTorchSampler(n_startup_trials=5)
670
+
671
+ os.chdir(os.path.dirname(__file__))
672
+
673
+ def _parabola(_fem: AbstractFEMInterface, _opt: AbstractOptimizer) -> float:
674
+ d = _opt.get_variables()
675
+ x1 = d['x1']
676
+ x2 = d['x2']
677
+ # if _cns(_fem, _opt) < 0:
678
+ # raise PostProcessError
679
+ return x1 ** 2 + x2 ** 2
680
+
681
+ def _parabola2(_fem: AbstractFEMInterface, _opt: AbstractOptimizer) -> float:
682
+ x = _opt.get_variables('values')
683
+ return ((x - 0.1) ** 2).sum()
684
+
685
+ def _cns(_fem: AbstractFEMInterface, _opt: AbstractOptimizer) -> float:
686
+ x = _opt.get_variables('values')
687
+ return x[0]
688
+
689
+ _fem = NoFEM()
690
+ _opt = OptunaOptimizer()
691
+ _opt.fem = _fem
692
+
693
+ # _opt.sampler = optuna.samplers.RandomSampler(seed=42)
694
+ _opt.seed = 42
695
+ _opt.sampler_class = optuna.samplers.TPESampler
696
+ # _opt.sampler_class = optuna.samplers.RandomSampler
697
+ _opt.sampler_kwargs = dict(
698
+ n_startup_trials=5,
699
+ )
700
+ _opt.n_trials = 10
701
+
702
+ _opt.add_parameter('x1', 1, -1, 1, step=0.1)
703
+ _opt.add_parameter('x2', 1, -1, 1, step=0.1)
704
+ _opt.add_categorical_parameter('x3', 'a', choices=['a', 'b', 'c'])
705
+ # _opt.add_constraint('cns', _cns, lower_bound=-0.9, args=(_opt,))
706
+ _opt.add_objective('obj1', _parabola, args=(_opt,))
707
+ # _opt.add_objective('obj2', _parabola2, args=(_opt,))
708
+
709
+ # ===== sub-fidelity =====
710
+ __fem = NoFEM()
711
+ __opt = SubFidelityModel()
712
+ __opt.fem = __fem
713
+ __opt.add_objective('obj1', _parabola, args=(__opt,))
714
+ # __opt.add_objective('obj2', _parabola2, args=(__opt,))
715
+
716
+ _opt.add_sub_fidelity_model(name='low-fidelity', sub_fidelity_model=__opt, fidelity=0.5)
717
+
718
+ def _solve_condition(_history: History):
719
+
720
+ sub_fidelity_df = _history.get_df(
721
+ {'sub_fidelity_name': 'low-fidelity'}
722
+ )
723
+ idx = sub_fidelity_df['state'] == TrialState.succeeded
724
+ pdf = sub_fidelity_df[idx]
725
+
726
+ return len(pdf) % 5 == 0
727
+
728
+ _opt.set_solve_condition(_solve_condition)
729
+
730
+ # _opt.history.path = 'restart-test.csv'
731
+ _opt.run()
732
+
733
+ # import plotly.express as px
734
+ # _df = _opt.history.get_df()
735
+ # px.scatter_3d(_df, x='x1', y='x2', z='obj', color='fidelity', opacity=0.5).show()
736
+
737
+ _opt.history.save()
738
+
739
+
740
+ def substrate_size(Femtet):
741
+ """基板のXY平面上での専有面積を計算します。"""
742
+ substrate_w = Femtet.GetVariableValue('substrate_w')
743
+ substrate_d = Femtet.GetVariableValue('substrate_d')
744
+ return substrate_w * substrate_d # 単位: mm2
745
+
746
+
747
+ def debug_2():
748
+ from pyfemtet.opt.interface._femtet_interface.femtet_interface import FemtetInterface
749
+
750
+ fem = FemtetInterface(
751
+ femprj_path=os.path.join(os.path.dirname(__file__), 'wat_ex14_parametric_jp.femprj'),
752
+ )
753
+
754
+ opt = OptunaOptimizer()
755
+
756
+ opt.fem = fem
757
+
758
+ opt.add_parameter(name="substrate_w", initial_value=40, lower_bound=22, upper_bound=60)
759
+ opt.add_parameter(name="substrate_d", initial_value=60, lower_bound=34, upper_bound=60)
760
+ opt.add_objective(name='基板サイズ(mm2)', fun=substrate_size)
761
+
762
+ opt.n_trials = 5
763
+ opt.history.path = os.path.join(os.path.dirname(__file__), 'femtet-test.csv')
764
+
765
+ opt.run()
766
+
767
+
768
+ def debug_3():
769
+ from pyfemtet.opt.interface._femtet_interface.femtet_interface import FemtetInterface
770
+
771
+ fem = FemtetInterface(
772
+ femprj_path=os.path.join(os.path.dirname(__file__), 'wat_ex14_parametric_jp.femprj'),
773
+ )
774
+
775
+ fem.use_parametric_output_as_objective(
776
+ number=1, direction='minimize',
777
+ )
778
+
779
+ opt = OptunaOptimizer()
780
+
781
+ opt.fem = fem
782
+
783
+ opt.add_parameter(name="substrate_w", initial_value=40, lower_bound=22, upper_bound=60)
784
+ opt.add_parameter(name="substrate_d", initial_value=60, lower_bound=34, upper_bound=60)
785
+
786
+ opt.n_trials = 5
787
+ opt.history.path = os.path.join(os.path.dirname(__file__), 'femtet-test-2.csv')
788
+
789
+ opt.run()
790
+
791
+
792
+ if __name__ == '__main__':
793
+ debug_1()
794
+ debug_1s()
795
+ debug_2()
796
+ debug_3()