pyfemtet 0.9.6__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.6.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.6.dist-info/RECORD +0 -158
  259. pyfemtet-0.9.6.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.6.dist-info → pyfemtet-1.0.0.dist-info}/LICENSE +0 -0
  271. {pyfemtet-0.9.6.dist-info → pyfemtet-1.0.0.dist-info}/LICENSE_THIRD_PARTY.txt +0 -0
  272. {pyfemtet-0.9.6.dist-info → pyfemtet-1.0.0.dist-info}/WHEEL +0 -0
@@ -0,0 +1,911 @@
1
+ from __future__ import annotations
2
+
3
+ import datetime
4
+ from typing import Callable, TypeAlias, Sequence, Literal
5
+ from numbers import Real # マイナーなので型ヒントでは使わず、isinstance で使う
6
+ from time import sleep
7
+
8
+ import sympy
9
+
10
+ from pyfemtet._i18n.messages import _
11
+ from pyfemtet.opt.history import *
12
+ from pyfemtet.opt.interface import *
13
+ from pyfemtet.opt.exceptions import *
14
+ from pyfemtet.opt.worker_status import *
15
+ from pyfemtet.opt.problem.problem import *
16
+ from pyfemtet.opt.problem.variable_manager import *
17
+ from pyfemtet.logger import get_module_logger
18
+
19
+ __all__ = [
20
+ 'AbstractOptimizer',
21
+ 'SubFidelityModel',
22
+ 'SubFidelityModels',
23
+ '_FReturnValue',
24
+ ]
25
+
26
+
27
+ DIRECTION: TypeAlias = (
28
+ float
29
+ | Literal[
30
+ 'minimize',
31
+ 'maximize',
32
+ ]
33
+ )
34
+
35
+ logger = get_module_logger('opt.optimizer', False)
36
+
37
+
38
+ def _log_hidden_constraint(e: Exception):
39
+ err_msg = create_err_msg_from_exception(e)
40
+ logger.warning(_('----- Hidden constraint violation! -----'))
41
+ logger.warning(_('error: {err_msg}', err_msg=err_msg))
42
+
43
+
44
+ _FReturnValue: TypeAlias = tuple[TrialOutput, dict[str, float], TrialConstraintOutput, Record]
45
+
46
+
47
+ def _duplicated_name_check(name, names):
48
+ if name in names:
49
+ logger.warning(
50
+ _(
51
+ en_message='There are duplicated name {name}. If there are '
52
+ 'duplicate names for parameters or objective '
53
+ 'functions, the later defined ones will overwrite '
54
+ 'the earlier ones. Please be careful to ensure '
55
+ 'that this overwriting is intentional.',
56
+ jp_message='名前 {name} が重複しています。パラメータや目的関数'
57
+ 'などの名前が重複すると、後から定義したものが上書き'
58
+ 'されます。この上書きが意図したものであるかどうか、'
59
+ '十分に注意してください。',
60
+ name=name,
61
+ )
62
+ )
63
+
64
+
65
+ class AbstractOptimizer:
66
+
67
+ # optimize
68
+ n_trials: int | None
69
+ timeout: float | None
70
+ seed: int | None
71
+
72
+ # problem
73
+ variable_manager: VariableManager
74
+ objectives: Objectives
75
+ constraints: Constraints
76
+ fidelity: Fidelity | None
77
+ sub_fidelity_name: str
78
+ sub_fidelity_models: SubFidelityModels | None
79
+
80
+ # system
81
+ history: History
82
+ fem: AbstractFEMInterface
83
+ entire_status: WorkerStatus
84
+ worker_status: WorkerStatus
85
+ worker_status_list: list[WorkerStatus]
86
+ _done_setup_before_parallel: bool
87
+ _done_load_problem_from_fem: bool
88
+ _worker_index: int | str | None
89
+ _worker_name: str | None
90
+
91
+ def __init__(self):
92
+
93
+ # optimization
94
+ self.seed = None
95
+ self.n_trials = None
96
+ self.timeout = None
97
+
98
+ # Problem
99
+ self.variable_manager = VariableManager()
100
+ self.objectives = Objectives()
101
+ self.constraints = Constraints()
102
+
103
+ # multi-fidelity
104
+ self.fidelity = None
105
+ self.sub_fidelity_name = MAIN_FIDELITY_NAME
106
+ self.sub_fidelity_models = SubFidelityModels()
107
+
108
+ # System
109
+ self.fem: AbstractFEMInterface | None = None
110
+ self.history: History = History()
111
+ self.solve_condition: Callable[[History], bool] = lambda _: True
112
+ self.entire_status: WorkerStatus = WorkerStatus(ENTIRE_PROCESS_STATUS_KEY)
113
+ self.worker_status: WorkerStatus = WorkerStatus('worker-status')
114
+ self.worker_status_list: list[WorkerStatus] = [self.worker_status]
115
+ self._done_setup_before_parallel = False
116
+ self._done_load_problem_from_fem = False
117
+ self._worker_index: int | str | None = None
118
+ self._worker_name: str | None = None
119
+
120
+ # ===== public =====
121
+
122
+ def add_constant_value(
123
+ self,
124
+ name: str,
125
+ value: SupportedVariableTypes,
126
+ properties: dict[str, ...] | None = None,
127
+ *,
128
+ pass_to_fem: bool = True,
129
+ ):
130
+ if isinstance(value, Real):
131
+ var = NumericVariable()
132
+ elif isinstance(value, str):
133
+ var = CategoricalVariable()
134
+ else:
135
+ raise ValueError(_(
136
+ en_message='Supported variable types are Real or str, got {type}',
137
+ jp_message='サポートされている変数の型は Real か str ですが、{type} が指定されました。',
138
+ type=type(value),
139
+ ))
140
+ var.name = name
141
+ var.value = value
142
+ var.pass_to_fem = pass_to_fem
143
+ var.properties = properties if properties is not None else {}
144
+ _duplicated_name_check(name, self.variable_manager.variables.keys())
145
+ self.variable_manager.variables.update({name: var})
146
+
147
+ def add_parameter(
148
+ self,
149
+ name: str,
150
+ initial_value: float | None = None,
151
+ lower_bound: float | None = None,
152
+ upper_bound: float | None = None,
153
+ step: float | None = None,
154
+ properties: dict[str, ...] | None = None,
155
+ *,
156
+ pass_to_fem: bool = True,
157
+ fix: bool = False,
158
+ ) -> None:
159
+ properties = properties if properties is not None else {}
160
+
161
+ if fix:
162
+ properties.update({'fix': True})
163
+
164
+ prm = NumericParameter()
165
+ prm.name = name
166
+ prm.value = initial_value
167
+ prm.lower_bound = lower_bound
168
+ prm.upper_bound = upper_bound
169
+ prm.step = step
170
+ prm.properties = properties
171
+ prm.pass_to_fem = pass_to_fem
172
+ _duplicated_name_check(name, self.variable_manager.variables.keys())
173
+ self.variable_manager.variables.update({name: prm})
174
+
175
+ def add_expression_string(
176
+ self,
177
+ name: str,
178
+ expression_string: str,
179
+ properties: dict[str, ...] | None = None,
180
+ *,
181
+ pass_to_fem: bool = True,
182
+ ) -> None:
183
+ var = ExpressionFromString()
184
+ var.name = name
185
+ var._expr = ExpressionFromString.InternalClass(expression_string=expression_string)
186
+ var.properties = properties or dict()
187
+ var.pass_to_fem = pass_to_fem
188
+ _duplicated_name_check(name, self.variable_manager.variables.keys())
189
+ self.variable_manager.variables.update({name: var})
190
+
191
+ def add_expression_sympy(
192
+ self,
193
+ name: str,
194
+ sympy_expr: sympy.Expr,
195
+ properties: dict[str, ...] | None = None,
196
+ *,
197
+ pass_to_fem: bool = True,
198
+ ) -> None:
199
+ var = ExpressionFromString()
200
+ var.name = name
201
+ var._expr = ExpressionFromString.InternalClass(sympy_expr=sympy_expr)
202
+ var.properties = properties or dict()
203
+ var.pass_to_fem = pass_to_fem
204
+ _duplicated_name_check(name, self.variable_manager.variables.keys())
205
+ self.variable_manager.variables.update({name: var})
206
+
207
+ def add_expression(
208
+ self,
209
+ name: str,
210
+ fun: Callable[..., float],
211
+ properties: dict[str, ...] | None = None,
212
+ args: tuple | None = None,
213
+ kwargs: dict | None = None,
214
+ *,
215
+ pass_to_fem: bool = True,
216
+ ) -> None:
217
+ var = ExpressionFromFunction()
218
+ var.name = name
219
+ var.fun = fun
220
+ var.args = args or tuple()
221
+ var.kwargs = kwargs or dict()
222
+ var.properties = properties or dict()
223
+ var.pass_to_fem = pass_to_fem
224
+ _duplicated_name_check(name, self.variable_manager.variables.keys())
225
+ self.variable_manager.variables.update({name: var})
226
+
227
+ def add_categorical_parameter(
228
+ self,
229
+ name: str,
230
+ initial_value: str | None = None,
231
+ choices: list[str] | None = None,
232
+ properties: dict[str, ...] | None = None,
233
+ *,
234
+ pass_to_fem: bool = True,
235
+ fix: bool = False,
236
+ ) -> None:
237
+ properties = properties if properties is not None else {}
238
+
239
+ if fix:
240
+ properties.update({'fix': True})
241
+
242
+ prm = CategoricalParameter()
243
+ prm.name = name
244
+ prm.value = initial_value
245
+ prm.choices = choices
246
+ prm.properties = properties
247
+ prm.pass_to_fem = pass_to_fem
248
+ _duplicated_name_check(name, self.variable_manager.variables.keys())
249
+ self.variable_manager.variables.update({name: prm})
250
+
251
+ def add_objective(
252
+ self,
253
+ name: str,
254
+ fun: Callable[..., float],
255
+ direction: DIRECTION = 'minimize',
256
+ args: tuple | None = None,
257
+ kwargs: dict | None = None,
258
+ ) -> None:
259
+ obj = Objective()
260
+ obj.fun = fun
261
+ obj.args = args or ()
262
+ obj.kwargs = kwargs or {}
263
+ obj.direction = direction
264
+ _duplicated_name_check(name, self.objectives.keys())
265
+ self.objectives.update({name: obj})
266
+
267
+ def add_objectives(
268
+ self,
269
+ names: str | list[str],
270
+ fun: Callable[..., Sequence[float]],
271
+ n_return: int,
272
+ directions: DIRECTION | Sequence[DIRECTION | None] | None = None,
273
+ args: tuple | None = None,
274
+ kwargs: dict | None = None,
275
+ ):
276
+ # argument processing
277
+ if isinstance(names, str):
278
+ names = [f'{names}_{i}' for i in range(n_return)]
279
+ elif isinstance(names, Sequence):
280
+ # names = names
281
+ pass
282
+ else:
283
+ raise ValueError(
284
+ _(en_message='`names` must be a string or an array of strings.',
285
+ jp_message='`names` は文字列か文字列の配列でなければなりません。',)
286
+ )
287
+
288
+ if directions is None:
289
+ directions = ['minimize' for __ in range(n_return)]
290
+ else:
291
+ if isinstance(directions, str) or isinstance(directions, Real):
292
+ directions = [directions for __ in range(n_return)]
293
+ else:
294
+ # directions = directions
295
+ pass
296
+
297
+ assert len(names) == len(directions) == n_return
298
+
299
+ function_factory = ObjectivesFunc(fun, n_return)
300
+ for i, (name, direction) in enumerate(zip(names, directions)):
301
+ fun_i = function_factory.get_fun_that_returns_ith_value(i)
302
+ self.add_objective(
303
+ fun=fun_i,
304
+ name=name,
305
+ direction=direction,
306
+ args=args,
307
+ kwargs=kwargs,
308
+ )
309
+
310
+ def add_constraint(
311
+ self,
312
+ name: str,
313
+ fun: Callable[..., float],
314
+ lower_bound: float | None = None,
315
+ upper_bound: float | None = None,
316
+ args: tuple | None = None,
317
+ kwargs: dict | None = None,
318
+ strict: bool = True,
319
+ using_fem: bool | None = None,
320
+ ):
321
+
322
+ if lower_bound is None and upper_bound is None:
323
+ raise ValueError(_(
324
+ en_message='One of `lower_bound` and `upper_bound` '
325
+ 'should be set.',
326
+ jp_message='`lower_bound` and `upper_bound` のうち'
327
+ '少なくとも一つは指定されなければなりません。'
328
+ ))
329
+
330
+ cns = Constraint()
331
+ cns.fun = fun
332
+ cns.args = args or ()
333
+ cns.kwargs = kwargs or {}
334
+ cns.lower_bound = lower_bound
335
+ cns.upper_bound = upper_bound
336
+ cns.hard = strict
337
+ cns._opt = self
338
+ cns.using_fem = using_fem
339
+ _duplicated_name_check(name, self.constraints.keys())
340
+ self.constraints.update({name: cns})
341
+
342
+ def add_sub_fidelity_model(
343
+ self,
344
+ name: str,
345
+ sub_fidelity_model: SubFidelityModel,
346
+ fidelity: Fidelity,
347
+ ):
348
+ sub_fidelity_model.variable_manager = self.variable_manager
349
+ if self.sub_fidelity_models is None:
350
+ self.sub_fidelity_models = SubFidelityModels()
351
+ self.fidelity = 1.
352
+ _duplicated_name_check(name, self.sub_fidelity_models.keys())
353
+ self.sub_fidelity_models._update(name, sub_fidelity_model, fidelity)
354
+
355
+ def get_variables(self, format='dict'):
356
+ return self.variable_manager.get_variables(
357
+ format=format,
358
+ )
359
+
360
+ def get_parameter(self, format='dict'):
361
+ return self.variable_manager.get_variables(
362
+ format=format, filter='parameter'
363
+ )
364
+
365
+ def set_solve_condition(self, fun: Callable[[History], bool]):
366
+ self.solve_condition = fun
367
+
368
+ # ===== private =====
369
+
370
+ def _should_solve(self, history):
371
+ return self.solve_condition(history)
372
+
373
+ def _y(self) -> TrialOutput:
374
+ out = TrialOutput()
375
+ for name, obj in self.objectives.items():
376
+ obj_result = ObjectiveResult(obj, self.fem)
377
+ out.update({name: obj_result})
378
+ return out
379
+
380
+ def _convert_y(self, y: TrialOutput) -> dict:
381
+ out = dict()
382
+ for name, result in y.items():
383
+ obj = self.objectives[name]
384
+ value_internal = obj.convert(result.value)
385
+ out.update({name: value_internal})
386
+ return out
387
+
388
+ def _hard_c(self, out: TrialConstraintOutput) -> TrialConstraintOutput:
389
+ for name, cns in self.constraints.items():
390
+ if cns.hard:
391
+ cns_result = ConstraintResult(cns, self.fem)
392
+ out.update({name: cns_result})
393
+ return out
394
+
395
+ def _soft_c(self, out: TrialConstraintOutput) -> TrialConstraintOutput:
396
+ for name, cns in self.constraints.items():
397
+ if not cns.hard:
398
+ cns_result = ConstraintResult(cns, self.fem)
399
+ out.update({name: cns_result})
400
+ return out
401
+
402
+ def _get_hard_constraint_violation_names(self, hard_c: TrialConstraintOutput) -> list[str]:
403
+ violation_names = []
404
+ for name, result in hard_c.items():
405
+ cns = self.constraints[name]
406
+ l_or_u = result.check_violation()
407
+ if l_or_u is not None:
408
+ logger.warning(_('----- Hard constraint violation! -----'))
409
+ logger.warning(_('constraint: {name}', name=name))
410
+ logger.warning(_('evaluated value: {value}', value=result.value))
411
+ if l_or_u == 'lower_bound':
412
+ logger.info(_('lower bound: {lb}', lb=cns.lower_bound))
413
+ violation_names.append(name + '_' + l_or_u)
414
+ elif l_or_u == 'upper_bound':
415
+ logger.info(_('upper bound: {ub}', ub=cns.upper_bound))
416
+ violation_names.append(name + '_' + l_or_u)
417
+ else:
418
+ raise NotImplementedError
419
+ return violation_names
420
+
421
+ def _check_and_raise_interruption(self) -> ...:
422
+ # raise Interrupt
423
+ interrupted = self.entire_status.value >= WorkerStatus.interrupting
424
+ if interrupted:
425
+ self.worker_status.value = WorkerStatus.interrupting
426
+ raise InterruptOptimization
427
+
428
+ # ===== solve =====
429
+
430
+ class _SolveSet:
431
+
432
+ opt: AbstractOptimizer
433
+ opt_: AbstractOptimizer
434
+
435
+ def __init__(self, opt: AbstractOptimizer):
436
+ self.opt: AbstractOptimizer = opt
437
+ self.subsampling_idx: SubSampling | None = None
438
+
439
+ def _preprocess(self):
440
+ pass
441
+
442
+ def _hard_constraint_handling(self, e: HardConstraintViolation):
443
+ pass
444
+
445
+ def _hidden_constraint_handling(self, e: _HiddenConstraintViolation):
446
+ pass
447
+
448
+ def _skip_handling(self, e: SkipSolve):
449
+ pass
450
+
451
+ def _if_succeeded(self, f_return: _FReturnValue):
452
+ pass
453
+
454
+ def _postprocess(self):
455
+ pass
456
+
457
+ def _solve_or_raise(
458
+ self,
459
+ opt_: AbstractOptimizer,
460
+ parameters: TrialInput,
461
+ variables_pass_to_fem: dict[str, SupportedVariableTypes],
462
+ history: History = None,
463
+ datetime_start=None,
464
+ trial_id=None,
465
+ ) -> _FReturnValue:
466
+
467
+ # create context
468
+ if history is not None:
469
+ record_to_history = history.recording(opt_.fem)
470
+ else:
471
+ class DummyRecordContext:
472
+ def __enter__(self):
473
+ return Record()
474
+
475
+ def __exit__(self, exc_type, exc_val, exc_tb):
476
+ pass
477
+
478
+ record_to_history = DummyRecordContext()
479
+
480
+ # processing with recording
481
+ with record_to_history as record:
482
+
483
+ # record common result
484
+ # input
485
+ record.x = parameters
486
+ # output (the value is nan, required for direction recording to graph)
487
+ record.y = TrialOutput(
488
+ {obj_name: ObjectiveResult(obj, opt_.fem, float('nan'))
489
+ for obj_name, obj in opt_.objectives.items()}
490
+ )
491
+ record.sub_sampling = self.subsampling_idx
492
+ record.trial_id = trial_id
493
+ record.sub_fidelity_name = opt_.sub_fidelity_name
494
+ record.fidelity = opt_.fidelity
495
+ record.datetime_start = datetime_start
496
+ if self.opt._worker_name is not None:
497
+ record.messages.append(self.opt._worker_name)
498
+
499
+ # check skip
500
+ if not opt_._should_solve(history):
501
+ record.state = TrialState.skipped
502
+ raise SkipSolve
503
+
504
+ # start solve
505
+ if opt_.sub_fidelity_name != MAIN_FIDELITY_NAME:
506
+ logger.info('----------')
507
+ logger.info(_('fidelity: ({name})', name=opt_.sub_fidelity_name))
508
+ logger.info(_('input variables:'))
509
+ logger.info(parameters)
510
+
511
+ # ===== update FEM parameter =====
512
+ logger.info(_('updating variables...'))
513
+ opt_.fem.update_parameter(variables_pass_to_fem)
514
+ opt_._check_and_raise_interruption()
515
+
516
+ # ===== evaluate hard constraint =====
517
+ logger.info(_('evaluating constraint functions...'))
518
+
519
+ hard_c = TrialConstraintOutput()
520
+ try:
521
+ opt_._hard_c(hard_c)
522
+
523
+ except _HiddenConstraintViolation as e:
524
+ _log_hidden_constraint(e)
525
+ record.c = hard_c
526
+ record.state = TrialState.get_corresponding_state_from_exception(e)
527
+ record.messages.append(
528
+ _('Hidden constraint violation '
529
+ 'during hard constraint function '
530
+ 'evaluation: ')
531
+ + create_err_msg_from_exception(e)
532
+ )
533
+
534
+ raise e
535
+
536
+ # check hard constraint violation
537
+ violation_names = opt_._get_hard_constraint_violation_names(hard_c)
538
+ if len(violation_names) > 0:
539
+ record.c = hard_c
540
+ record.state = TrialState.hard_constraint_violation
541
+ record.messages.append(
542
+ _('Hard constraint violation: ')
543
+ + ', '.join(violation_names))
544
+
545
+ raise HardConstraintViolation
546
+
547
+ # ===== update FEM =====
548
+ logger.info(_('Solving FEM...'))
549
+
550
+ try:
551
+ opt_.fem.update()
552
+ opt_._check_and_raise_interruption()
553
+
554
+ # if hidden constraint violation
555
+ except _HiddenConstraintViolation as e:
556
+
557
+ opt_._check_and_raise_interruption()
558
+
559
+ _log_hidden_constraint(e)
560
+ record.c = hard_c
561
+ record.state = TrialState.get_corresponding_state_from_exception(e)
562
+ record.messages.append(
563
+ _('Hidden constraint violation in FEM update: ')
564
+ + create_err_msg_from_exception(e))
565
+
566
+ raise e
567
+
568
+ # ===== evaluate y =====
569
+ logger.info(_('evaluating objective functions...'))
570
+
571
+ try:
572
+ y: TrialOutput = opt_._y()
573
+ opt_._check_and_raise_interruption()
574
+
575
+ # if intentional error (by user)
576
+ except _HiddenConstraintViolation as e:
577
+ opt_._check_and_raise_interruption()
578
+
579
+ _log_hidden_constraint(e)
580
+ record.c = hard_c
581
+ record.state = TrialState.get_corresponding_state_from_exception(e)
582
+ record.messages.append(
583
+ _('Hidden constraint violation during '
584
+ 'objective function evaluation: ')
585
+ + create_err_msg_from_exception(e))
586
+
587
+ raise e
588
+
589
+ # ===== evaluate soft constraint =====
590
+ logger.info(_('evaluating remaining constraints...'))
591
+
592
+ soft_c = TrialConstraintOutput()
593
+ try:
594
+ opt_._soft_c(soft_c)
595
+
596
+ # if intentional error (by user)
597
+ except _HiddenConstraintViolation as e:
598
+ _log_hidden_constraint(e)
599
+
600
+ _c = {}
601
+ _c.update(soft_c)
602
+ _c.update(hard_c)
603
+
604
+ record.y = y
605
+ record.c = _c
606
+ record.state = TrialState.get_corresponding_state_from_exception(e)
607
+ record.messages.append(
608
+ _('Hidden constraint violation during '
609
+ 'soft constraint function evaluation: ')
610
+ + create_err_msg_from_exception(e))
611
+
612
+ raise e
613
+
614
+ # ===== merge and sort constraints =====
615
+ c = TrialConstraintOutput()
616
+ c.update(soft_c)
617
+ c.update(hard_c)
618
+
619
+ # get values as minimize
620
+ y_internal: dict = opt_._convert_y(y)
621
+
622
+ logger.info(_('output:'))
623
+ logger.info(y)
624
+ record.y = y
625
+ record.c = c
626
+ record.state = TrialState.succeeded
627
+
628
+ opt_._check_and_raise_interruption()
629
+
630
+ return y, y_internal, c, record
631
+
632
+ def solve(
633
+ self,
634
+ x: TrialInput,
635
+ x_pass_to_fem_: dict[str, SupportedVariableTypes],
636
+ opt_: AbstractOptimizer | None = None,
637
+ trial_id: str =None,
638
+ ) -> _FReturnValue | None:
639
+ """Nothing will be raised even if infeasible."""
640
+
641
+ vm = self.opt.variable_manager
642
+
643
+ # opt_ はメインの opt 又は sub_fidelity
644
+ opt_ = opt_ or self.opt
645
+ self.opt_ = opt_
646
+
647
+ # check interruption
648
+ self.opt._check_and_raise_interruption()
649
+
650
+ # if opt_ is not self, update variable manager
651
+ opt_.variable_manager = vm
652
+
653
+ # noinspection PyMethodParameters
654
+ class Process:
655
+ def __enter__(self_):
656
+ # preprocess
657
+ self._preprocess()
658
+
659
+ def __exit__(self_, exc_type, exc_val, exc_tb):
660
+ # postprocess
661
+ self._postprocess()
662
+
663
+ with Process():
664
+
665
+ # declare output
666
+ f_return = None
667
+
668
+ # start solve
669
+ datetime_start = datetime.datetime.now()
670
+ try:
671
+ f_return = self._solve_or_raise(
672
+ opt_, x, x_pass_to_fem_, self.opt.history,
673
+ datetime_start, trial_id
674
+ )
675
+
676
+ except HardConstraintViolation as e:
677
+ self._hard_constraint_handling(e)
678
+
679
+ except _HiddenConstraintViolation as e:
680
+ self._hidden_constraint_handling(e)
681
+
682
+ except SkipSolve as e:
683
+ self._skip_handling(e)
684
+
685
+ else:
686
+ self._if_succeeded(f_return)
687
+
688
+ # check interruption
689
+ self.opt._check_and_raise_interruption()
690
+
691
+ return f_return
692
+
693
+ def _get_solve_set(self):
694
+ return self._SolveSet(self)
695
+
696
+ # ===== run and setup =====
697
+
698
+ def _setting_status(self):
699
+
700
+ # noinspection PyMethodParameters
701
+ class _SettingStatus:
702
+
703
+ def __enter__(self_):
704
+ pass
705
+
706
+ def __exit__(self_, exc_type, exc_val, exc_tb):
707
+ if exc_type is not None:
708
+ if self.worker_status.value < WorkerStatus.crashed:
709
+ self.worker_status.value = WorkerStatus.crashed
710
+ else:
711
+ if self.worker_status.value < WorkerStatus.finishing:
712
+ self.worker_status.value = WorkerStatus.finishing
713
+
714
+ return _SettingStatus()
715
+
716
+ def run(self) -> None:
717
+ raise NotImplementedError
718
+
719
+ def _run(
720
+ self,
721
+ worker_idx: int | str,
722
+ worker_name: str,
723
+ history: History,
724
+ entire_status: WorkerStatus,
725
+ worker_status: WorkerStatus,
726
+ worker_status_list: list[WorkerStatus],
727
+ wait_other_process_setup: bool,
728
+ ) -> None:
729
+
730
+ self.history = history
731
+ self.entire_status = entire_status
732
+ self.worker_status = worker_status
733
+ self._worker_index = worker_idx
734
+ self._worker_name = worker_name
735
+ self.worker_status_list = worker_status_list
736
+
737
+ class SettingStatusFinished:
738
+
739
+ # noinspection PyMethodParameters
740
+ def __enter__(self_):
741
+ pass
742
+
743
+ # noinspection PyMethodParameters
744
+ def __exit__(self_, exc_type, exc_val, exc_tb):
745
+ if exc_type is not None:
746
+ self.worker_status.value = WorkerStatus.crashed
747
+
748
+ import sys
749
+ from traceback import print_tb
750
+ print(
751
+ _(
752
+ '===== Exception raised in worker {worker_idx} =====',
753
+ worker_idx=worker_idx
754
+ ),
755
+ file=sys.stderr
756
+ )
757
+ print_tb(exc_tb)
758
+ print(
759
+ _(
760
+ '{name}: {exc_val}',
761
+ name=exc_type.__name__,
762
+ exc_val=exc_val
763
+ ),
764
+ file=sys.stderr
765
+ )
766
+
767
+ else:
768
+ self.worker_status.value = WorkerStatus.finished
769
+
770
+ logger.info(_(
771
+ en_message='worker `{worker}` started.',
772
+ worker=worker_name,
773
+ ))
774
+
775
+ with SettingStatusFinished():
776
+
777
+ self.worker_status.value = WorkerStatus.initializing
778
+
779
+ self.worker_status.value = WorkerStatus.launching_fem
780
+ self.fem._setup_after_parallel(self)
781
+
782
+ if wait_other_process_setup:
783
+ self.worker_status.value = WorkerStatus.waiting
784
+ while True:
785
+ self._check_and_raise_interruption()
786
+
787
+ # 他のすべての worker_status が wait 以上になったら break
788
+ logger.debug([ws.value for ws in worker_status_list])
789
+ if all([ws.value >= WorkerStatus.waiting
790
+ for ws in worker_status_list]):
791
+
792
+ # リソースの競合等を避けるため
793
+ # break する前に index 秒待つ
794
+ if isinstance(worker_idx, str):
795
+ wait_second = 0.
796
+ else:
797
+ wait_second = int(worker_idx + 1)
798
+ sleep(wait_second)
799
+ break
800
+
801
+ sleep(1)
802
+
803
+ self.worker_status.value = WorkerStatus.running
804
+
805
+ self.run()
806
+
807
+ logger.info(_(
808
+ en_message='worker `{worker}` successfully finished!',
809
+ worker=worker_name,
810
+ ))
811
+
812
+ def _logging(self):
813
+
814
+ # noinspection PyMethodParameters
815
+ class LoggingOutput:
816
+ def __enter__(self_):
817
+ df = self.history.get_df(
818
+ equality_filters=MAIN_FILTER
819
+ )
820
+ self_.count = len(df) + 1
821
+
822
+ succeeded_count = len(df[df['state'] == TrialState.succeeded])
823
+ succeeded_text = _(
824
+ en_message='{succeeded_count} succeeded trials',
825
+ jp_message='成功した試行数: {succeeded_count}',
826
+ succeeded_count=succeeded_count,
827
+ )
828
+
829
+ logger.info(f'▼▼▼▼▼ solve {self_.count} ({succeeded_text}) start ▼▼▼▼▼')
830
+
831
+ def __exit__(self_, exc_type, exc_val, exc_tb):
832
+ logger.info(f'▲▲▲▲▲ solve {self_.count} end ▲▲▲▲▲\n')
833
+
834
+ return LoggingOutput()
835
+
836
+ def _load_problem_from_fem(self):
837
+ if self.fem._load_problem_from_fem and not self._done_load_problem_from_fem:
838
+ self.fem.load_variables(self)
839
+ self.fem.load_objectives(self)
840
+ self.fem.load_constraints(self)
841
+ self._done_load_problem_from_fem = True
842
+
843
+ # noinspection PyMethodMayBeStatic
844
+ def _get_additional_data(self) -> dict:
845
+ return dict()
846
+
847
+ def _collect_additional_data(self) -> dict:
848
+ additional_data = {}
849
+ additional_data.update(self._get_additional_data())
850
+ additional_data.update(self.fem._get_additional_data())
851
+ return additional_data
852
+
853
+ def _finalize_history(self):
854
+ if not self.history._finalized:
855
+ parameters = self.variable_manager.get_variables(
856
+ filter='parameter', format='raw'
857
+ )
858
+ self.history.finalize(
859
+ parameters,
860
+ list(self.objectives.keys()),
861
+ list(self.constraints.keys()),
862
+ [self.sub_fidelity_name] + list(self.sub_fidelity_models.keys()),
863
+ additional_data=self._collect_additional_data()
864
+ )
865
+
866
+ def _setup_before_parallel(self):
867
+
868
+ if not self._done_setup_before_parallel:
869
+
870
+ # check compatibility with fem if needed
871
+ variables = self.variable_manager.get_variables()
872
+ for var_name, variable in variables.items():
873
+ if variable.pass_to_fem:
874
+ self.fem._check_param_and_raise(var_name)
875
+
876
+ # resolve evaluation order
877
+ self.variable_manager.resolve()
878
+
879
+ self._done_setup_before_parallel = True
880
+
881
+ def _setup_after_parallel(self):
882
+ pass
883
+
884
+ def _finalize(self):
885
+
886
+ # check sub fidelity models
887
+ if self.sub_fidelity_models is None:
888
+ self.sub_fidelity_models = SubFidelityModels()
889
+ for sub_fidelity_model in self.sub_fidelity_models.values():
890
+ assert sub_fidelity_model.objectives.keys() == self.objectives.keys()
891
+ assert sub_fidelity_model.constraints.keys() == self.constraints.keys()
892
+
893
+ # finalize
894
+ self._load_problem_from_fem()
895
+ self._finalize_history()
896
+
897
+ # setup if needed
898
+ self._setup_before_parallel()
899
+ self._setup_after_parallel()
900
+
901
+
902
+ class SubFidelityModel(AbstractOptimizer):
903
+ pass
904
+
905
+
906
+ class SubFidelityModels(dict[str, SubFidelityModel]):
907
+
908
+ def _update(self, name, model: SubFidelityModel, fidelity: Fidelity):
909
+ model.sub_fidelity_name = name
910
+ model.fidelity = fidelity
911
+ self.update({name: model})