pyfemtet 0.9.5__py3-none-any.whl → 1.0.0a0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of pyfemtet might be problematic. Click here for more details.

Files changed (272) hide show
  1. pyfemtet/__init__.py +6 -1
  2. pyfemtet/_i18n/1. make_pot_and_update_po.bat +8 -0
  3. pyfemtet/_i18n/2. build_mo.bat +5 -0
  4. pyfemtet/_i18n/__init__.py +4 -0
  5. pyfemtet/_i18n/babel.cfg +2 -0
  6. pyfemtet/_i18n/i18n.py +37 -0
  7. pyfemtet/_i18n/locales/ja/LC_MESSAGES/messages.mo +0 -0
  8. pyfemtet/_i18n/locales/ja/LC_MESSAGES/messages.po +1020 -0
  9. pyfemtet/_i18n/locales/messages.pot +987 -0
  10. pyfemtet/{_message → _i18n}/messages.py +128 -41
  11. pyfemtet/_util/closing.py +19 -0
  12. pyfemtet/_util/dask_util.py +89 -7
  13. pyfemtet/_util/df_util.py +29 -0
  14. pyfemtet/_util/excel_macro_util.py +8 -3
  15. pyfemtet/_util/excel_parse_util.py +43 -23
  16. pyfemtet/_util/femtet_access_inspection.py +120 -0
  17. pyfemtet/{_femtet_config_util/autosave.py → _util/femtet_autosave.py} +7 -0
  18. pyfemtet/_util/femtet_exit.py +105 -0
  19. pyfemtet/_util/femtet_version.py +20 -0
  20. pyfemtet/_util/helper.py +94 -0
  21. pyfemtet/_util/process_util.py +107 -0
  22. pyfemtet/_util/str_enum.py +44 -0
  23. pyfemtet/core.py +15 -47
  24. pyfemtet/dispatch_extensions/__init__.py +8 -11
  25. pyfemtet/dispatch_extensions/_impl.py +42 -198
  26. pyfemtet/logger/__init__.py +8 -1
  27. pyfemtet/logger/_impl.py +5 -6
  28. pyfemtet/opt/__init__.py +3 -19
  29. pyfemtet/opt/exceptions.py +45 -0
  30. pyfemtet/opt/femopt.py +602 -0
  31. pyfemtet/opt/history/__init__.py +11 -0
  32. pyfemtet/opt/history/_history.py +1404 -0
  33. pyfemtet/opt/history/_hypervolume.py +169 -0
  34. pyfemtet/opt/history/_optimality.py +79 -0
  35. pyfemtet/opt/interface/__init__.py +17 -24
  36. pyfemtet/opt/interface/_base_interface.py +222 -0
  37. pyfemtet/opt/interface/_excel_interface/__init__.py +3 -0
  38. pyfemtet/opt/interface/_excel_interface/debug-excel-interface.xlsm +0 -0
  39. pyfemtet/opt/interface/_excel_interface/excel_interface.py +999 -0
  40. pyfemtet/opt/interface/_femtet_interface/__init__.py +3 -0
  41. pyfemtet/opt/interface/{_femtet_parametric.py → _femtet_interface/_femtet_parametric.py} +20 -12
  42. pyfemtet/opt/interface/{_femtet.py → _femtet_interface/femtet_interface.py} +490 -348
  43. pyfemtet/opt/interface/_femtet_with_nx_interface/__init__.py +5 -0
  44. pyfemtet/opt/interface/_femtet_with_nx_interface/femtet_with_nx_interface.py +230 -0
  45. pyfemtet/opt/interface/_femtet_with_nx_interface/model1.prt +0 -0
  46. pyfemtet/opt/interface/_femtet_with_nx_interface/model1.x_t +98 -0
  47. pyfemtet/opt/interface/{_femtet_with_nx → _femtet_with_nx_interface}/update_model.py +1 -3
  48. pyfemtet/opt/interface/_femtet_with_solidworks/__init__.py +5 -0
  49. pyfemtet/opt/interface/_femtet_with_solidworks/femtet_with_solidworks_interface.py +122 -0
  50. pyfemtet/opt/interface/_solidworks_interface/__init__.py +5 -0
  51. pyfemtet/opt/interface/_solidworks_interface/solidworks_interface.py +206 -0
  52. pyfemtet/opt/interface/_surrogate/_base.py +0 -129
  53. pyfemtet/opt/interface/_surrogate_model_interface/__init__.py +8 -0
  54. pyfemtet/opt/interface/_surrogate_model_interface/base_surrogate_interface.py +59 -0
  55. pyfemtet/opt/interface/_surrogate_model_interface/botorch_interface.py +271 -0
  56. pyfemtet/opt/interface/_surrogate_model_interface/debug-pof-botorch.reccsv +18 -0
  57. pyfemtet/opt/interface/_with_excel_settings/__init__.py +61 -0
  58. pyfemtet/opt/interface/_with_excel_settings/with_excel_settings.py +134 -0
  59. pyfemtet/opt/meta_script/YAML_Generator.xlsm +0 -0
  60. pyfemtet/opt/meta_script/__main__.py +58 -36
  61. pyfemtet/opt/optimizer/__init__.py +7 -9
  62. pyfemtet/opt/optimizer/_base_optimizer.py +876 -0
  63. pyfemtet/opt/optimizer/optuna_optimizer/__init__.py +9 -0
  64. pyfemtet/opt/optimizer/optuna_optimizer/_optuna_attribute.py +73 -0
  65. pyfemtet/opt/optimizer/optuna_optimizer/_optuna_optimizer.py +678 -0
  66. pyfemtet/opt/optimizer/optuna_optimizer/_pof_botorch/__init__.py +7 -0
  67. pyfemtet/opt/optimizer/optuna_optimizer/_pof_botorch/debug-pof-botorch.reccsv +18 -0
  68. pyfemtet/opt/optimizer/optuna_optimizer/_pof_botorch/enable_nonlinear_constraint.py +244 -0
  69. pyfemtet/opt/optimizer/optuna_optimizer/_pof_botorch/pof_botorch_sampler.py +1249 -0
  70. pyfemtet/opt/optimizer/optuna_optimizer/wat_ex14_parametric_jp.femprj +0 -0
  71. pyfemtet/opt/optimizer/scipy_optimizer/__init__.py +1 -0
  72. pyfemtet/opt/optimizer/scipy_optimizer/_scipy_optimizer.py +364 -0
  73. pyfemtet/opt/prediction/__init__.py +7 -0
  74. pyfemtet/opt/prediction/_botorch_utils.py +133 -0
  75. pyfemtet/opt/prediction/_gpytorch_modules_extension.py +142 -0
  76. pyfemtet/opt/prediction/_helper.py +155 -0
  77. pyfemtet/opt/prediction/_model.py +118 -0
  78. pyfemtet/opt/problem/problem.py +304 -0
  79. pyfemtet/opt/problem/variable_manager/__init__.py +20 -0
  80. pyfemtet/opt/problem/variable_manager/_string_as_expression.py +115 -0
  81. pyfemtet/opt/problem/variable_manager/_variable_manager.py +295 -0
  82. pyfemtet/opt/visualization/history_viewer/__main__.py +5 -0
  83. pyfemtet/opt/visualization/{_base.py → history_viewer/_base_application.py} +18 -13
  84. pyfemtet/opt/visualization/history_viewer/_common_pages.py +150 -0
  85. pyfemtet/opt/visualization/{_complex_components → history_viewer/_complex_components}/alert_region.py +10 -5
  86. pyfemtet/opt/visualization/{_complex_components → history_viewer/_complex_components}/control_femtet.py +16 -13
  87. pyfemtet/opt/visualization/{_complex_components → history_viewer/_complex_components}/main_graph.py +117 -47
  88. pyfemtet/opt/visualization/{_complex_components → history_viewer/_complex_components}/pm_graph.py +159 -138
  89. pyfemtet/opt/visualization/history_viewer/_process_monitor/_application.py +173 -0
  90. pyfemtet/opt/visualization/history_viewer/_process_monitor/_pages.py +291 -0
  91. pyfemtet/opt/visualization/{_wrapped_components → history_viewer/_wrapped_components}/dbc.py +1 -1
  92. pyfemtet/opt/visualization/{_wrapped_components → history_viewer/_wrapped_components}/dcc.py +1 -1
  93. pyfemtet/opt/visualization/{_wrapped_components → history_viewer/_wrapped_components}/html.py +1 -1
  94. pyfemtet/opt/visualization/history_viewer/result_viewer/__main__.py +5 -0
  95. pyfemtet/opt/visualization/{result_viewer/application.py → history_viewer/result_viewer/_application.py} +6 -6
  96. pyfemtet/opt/visualization/{result_viewer/pages.py → history_viewer/result_viewer/_pages.py} +106 -82
  97. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08.csv +18 -0
  98. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08.db +0 -0
  99. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8.jpg +0 -0
  100. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8.log +45 -0
  101. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8.pdt +0 -0
  102. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_1.jpg +0 -0
  103. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_1.pdt +0 -0
  104. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_10.jpg +0 -0
  105. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_10.pdt +0 -0
  106. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_11.jpg +0 -0
  107. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_11.pdt +0 -0
  108. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_12.jpg +0 -0
  109. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_12.pdt +0 -0
  110. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_13.jpg +0 -0
  111. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_13.pdt +0 -0
  112. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_14.jpg +0 -0
  113. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_14.pdt +0 -0
  114. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_15.jpg +0 -0
  115. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_15.pdt +0 -0
  116. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_16.jpg +0 -0
  117. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_16.pdt +0 -0
  118. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_17.jpg +0 -0
  119. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_17.pdt +0 -0
  120. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_18.jpg +0 -0
  121. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_18.pdt +0 -0
  122. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_19.jpg +0 -0
  123. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_19.pdt +0 -0
  124. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_2.jpg +0 -0
  125. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_2.pdt +0 -0
  126. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_20.jpg +0 -0
  127. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_20.pdt +0 -0
  128. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_3.jpg +0 -0
  129. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_3.pdt +0 -0
  130. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_4.bgr +0 -0
  131. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_4.bnd +0 -0
  132. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_4.btr +0 -0
  133. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_4.jpg +0 -0
  134. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_4.mtl +0 -0
  135. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_4.pdt +0 -0
  136. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_4.prm +0 -0
  137. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_5.jpg +0 -0
  138. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_5.pdt +0 -0
  139. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_6.jpg +0 -0
  140. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_6.pdt +0 -0
  141. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_7.jpg +0 -0
  142. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_7.pdt +0 -0
  143. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_8.jpg +0 -0
  144. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_8.pdt +0 -0
  145. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_9.jpg +0 -0
  146. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_9.pdt +0 -0
  147. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.femprj +0 -0
  148. pyfemtet/opt/visualization/plotter/main_figure_creator.py +536 -0
  149. pyfemtet/opt/visualization/plotter/pm_graph_creator.py +359 -0
  150. pyfemtet/opt/worker_status.py +120 -0
  151. {pyfemtet-0.9.5.dist-info → pyfemtet-1.0.0a0.dist-info}/METADATA +22 -24
  152. pyfemtet-1.0.0a0.dist-info/RECORD +173 -0
  153. pyfemtet-1.0.0a0.dist-info/entry_points.txt +3 -0
  154. pyfemtet/_femtet_config_util/exit.py +0 -59
  155. pyfemtet/_message/1. make_pot.bat +0 -11
  156. pyfemtet/_message/2. make_mo.bat +0 -6
  157. pyfemtet/_message/__init__.py +0 -5
  158. pyfemtet/_message/babel.cfg +0 -2
  159. pyfemtet/_message/locales/ja/LC_MESSAGES/messages.mo +0 -0
  160. pyfemtet/_message/locales/ja/LC_MESSAGES/messages.po +0 -570
  161. pyfemtet/_message/locales/messages.pot +0 -551
  162. pyfemtet/_warning.py +0 -87
  163. pyfemtet/brep/_impl.py +0 -18
  164. pyfemtet/opt/_femopt.py +0 -1007
  165. pyfemtet/opt/_femopt_core.py +0 -1169
  166. pyfemtet/opt/_test_utils/control_femtet.py +0 -39
  167. pyfemtet/opt/_test_utils/hyper_sphere.py +0 -24
  168. pyfemtet/opt/_test_utils/record_history.py +0 -130
  169. pyfemtet/opt/advanced_samples/excel_ui/(ref) original_project.femprj +0 -0
  170. pyfemtet/opt/advanced_samples/excel_ui/femtet-macro.xlsm +0 -0
  171. pyfemtet/opt/advanced_samples/excel_ui/pyfemtet-core.py +0 -291
  172. pyfemtet/opt/advanced_samples/excel_ui/test-pyfemtet-core.cmd +0 -22
  173. pyfemtet/opt/advanced_samples/restart/gal_ex13_parametric.femprj +0 -0
  174. pyfemtet/opt/advanced_samples/restart/gal_ex13_parametric_restart.py +0 -99
  175. pyfemtet/opt/advanced_samples/restart/gal_ex13_parametric_restart_jp.py +0 -102
  176. pyfemtet/opt/advanced_samples/surrogate_model/gal_ex13_create_training_data.py +0 -60
  177. pyfemtet/opt/advanced_samples/surrogate_model/gal_ex13_create_training_data_jp.py +0 -57
  178. pyfemtet/opt/advanced_samples/surrogate_model/gal_ex13_optimize_with_surrogate.py +0 -100
  179. pyfemtet/opt/advanced_samples/surrogate_model/gal_ex13_optimize_with_surrogate_jp.py +0 -90
  180. pyfemtet/opt/advanced_samples/surrogate_model/gal_ex13_parametric.femprj +0 -0
  181. pyfemtet/opt/interface/_base.py +0 -101
  182. pyfemtet/opt/interface/_excel_interface.py +0 -984
  183. pyfemtet/opt/interface/_femtet_excel.py +0 -141
  184. pyfemtet/opt/interface/_femtet_with_nx/__init__.py +0 -3
  185. pyfemtet/opt/interface/_femtet_with_nx/_interface.py +0 -178
  186. pyfemtet/opt/interface/_femtet_with_sldworks.py +0 -298
  187. pyfemtet/opt/interface/_surrogate/__init__.py +0 -5
  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.0a0.dist-info}/LICENSE +0 -0
  271. {pyfemtet-0.9.5.dist-info → pyfemtet-1.0.0a0.dist-info}/LICENSE_THIRD_PARTY.txt +0 -0
  272. {pyfemtet-0.9.5.dist-info → pyfemtet-1.0.0a0.dist-info}/WHEEL +0 -0
@@ -0,0 +1,876 @@
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', True)
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
+ ) -> None:
181
+ var = ExpressionFromString()
182
+ var.name = name
183
+ var._expr = ExpressionFromString.InternalClass(expression_string=expression_string)
184
+ var.properties = properties or dict()
185
+ _duplicated_name_check(name, self.variable_manager.variables.keys())
186
+ self.variable_manager.variables.update({name: var})
187
+
188
+ def add_expression_sympy(
189
+ self,
190
+ name: str,
191
+ sympy_expr: sympy.Expr,
192
+ properties: dict[str, ...] | None = None,
193
+ ) -> None:
194
+ var = ExpressionFromString()
195
+ var.name = name
196
+ var._expr = ExpressionFromString.InternalClass(sympy_expr=sympy_expr)
197
+ var.properties = properties or dict()
198
+ _duplicated_name_check(name, self.variable_manager.variables.keys())
199
+ self.variable_manager.variables.update({name: var})
200
+
201
+ def add_expression(
202
+ self,
203
+ name: str,
204
+ fun: Callable[..., float],
205
+ properties: dict[str, ...] | None = None,
206
+ args: tuple | None = None,
207
+ kwargs: dict | None = None,
208
+ ) -> None:
209
+ var = ExpressionFromFunction()
210
+ var.name = name
211
+ var.fun = fun
212
+ var.args = args or tuple()
213
+ var.kwargs = kwargs or dict()
214
+ var.properties = properties or dict()
215
+ _duplicated_name_check(name, self.variable_manager.variables.keys())
216
+ self.variable_manager.variables.update({name: var})
217
+
218
+ def add_categorical_parameter(
219
+ self,
220
+ name: str,
221
+ initial_value: str | None = None,
222
+ choices: list[str] | None = None,
223
+ properties: dict[str, ...] | None = None,
224
+ *,
225
+ pass_to_fem: bool = True,
226
+ fix: bool = False,
227
+ ) -> None:
228
+ properties = properties if properties is not None else {}
229
+
230
+ if fix:
231
+ properties.update({'fix': True})
232
+
233
+ prm = CategoricalParameter()
234
+ prm.name = name
235
+ prm.value = initial_value
236
+ prm.choices = choices
237
+ prm.properties = properties
238
+ prm.pass_to_fem = pass_to_fem
239
+ _duplicated_name_check(name, self.variable_manager.variables.keys())
240
+ self.variable_manager.variables.update({name: prm})
241
+
242
+ def add_objective(
243
+ self,
244
+ name: str,
245
+ fun: Callable[..., float],
246
+ direction: DIRECTION = 'minimize',
247
+ args: tuple | None = None,
248
+ kwargs: dict | None = None,
249
+ ) -> None:
250
+ obj = Objective()
251
+ obj.fun = fun
252
+ obj.args = args or ()
253
+ obj.kwargs = kwargs or {}
254
+ obj.direction = direction
255
+ _duplicated_name_check(name, self.objectives.keys())
256
+ self.objectives.update({name: obj})
257
+
258
+ def add_objectives(
259
+ self,
260
+ names: str | list[str],
261
+ fun: Callable[..., Sequence[float]],
262
+ n_return: int,
263
+ directions: DIRECTION | Sequence[DIRECTION | None] | None = None,
264
+ args: tuple | None = None,
265
+ kwargs: dict | None = None,
266
+ ):
267
+ # argument processing
268
+ if isinstance(names, str):
269
+ names = [f'{names}_{i}' for i in range(n_return)]
270
+ elif isinstance(names, Sequence):
271
+ # names = names
272
+ pass
273
+ else:
274
+ raise ValueError(
275
+ _(en_message='`names` must be a string or an array of strings.',
276
+ jp_message='`names` は文字列か文字列の配列でなければなりません。',)
277
+ )
278
+
279
+ if directions is None:
280
+ directions = ['minimize' for __ in range(n_return)]
281
+ else:
282
+ if isinstance(directions, str) or isinstance(directions, Real):
283
+ directions = [directions for __ in range(n_return)]
284
+ else:
285
+ # directions = directions
286
+ pass
287
+
288
+ assert len(names) == len(directions) == n_return
289
+
290
+ function_factory = ObjectivesFunc(fun, n_return)
291
+ for i, (name, direction) in enumerate(zip(names, directions)):
292
+ fun_i = function_factory.get_fun_that_returns_ith_value(i)
293
+ self.add_objective(
294
+ fun=fun_i,
295
+ name=name,
296
+ direction=direction,
297
+ args=args,
298
+ kwargs=kwargs,
299
+ )
300
+
301
+ def add_constraint(
302
+ self,
303
+ name: str,
304
+ fun: Callable[..., float],
305
+ lower_bound: float | None = None,
306
+ upper_bound: float | None = None,
307
+ args: tuple | None = None,
308
+ kwargs: dict | None = None,
309
+ strict: bool = True,
310
+ using_fem: bool | None = None,
311
+ ):
312
+
313
+ if lower_bound is None and upper_bound is None:
314
+ raise ValueError(_(
315
+ en_message='One of `lower_bound` and `upper_bound` '
316
+ 'should be set.',
317
+ jp_message='`lower_bound` and `upper_bound` のうち'
318
+ '少なくとも一つは指定されなければなりません。'
319
+ ))
320
+
321
+ cns = Constraint()
322
+ cns.fun = fun
323
+ cns.args = args or ()
324
+ cns.kwargs = kwargs or {}
325
+ cns.lower_bound = lower_bound
326
+ cns.upper_bound = upper_bound
327
+ cns.hard = strict
328
+ cns._opt = self
329
+ cns.using_fem = using_fem
330
+ _duplicated_name_check(name, self.constraints.keys())
331
+ self.constraints.update({name: cns})
332
+
333
+ def add_sub_fidelity_model(
334
+ self,
335
+ name: str,
336
+ sub_fidelity_model: SubFidelityModel,
337
+ fidelity: Fidelity,
338
+ ):
339
+ sub_fidelity_model.variable_manager = self.variable_manager
340
+ if self.sub_fidelity_models is None:
341
+ self.sub_fidelity_models = SubFidelityModels()
342
+ self.fidelity = 1.
343
+ _duplicated_name_check(name, self.sub_fidelity_models.keys())
344
+ self.sub_fidelity_models._update(name, sub_fidelity_model, fidelity)
345
+
346
+ def get_variables(self, format='dict'):
347
+ return self.variable_manager.get_variables(
348
+ format=format,
349
+ )
350
+
351
+ def get_parameter(self, format='dict'):
352
+ return self.variable_manager.get_variables(
353
+ format=format, filter='parameter'
354
+ )
355
+
356
+ def set_solve_condition(self, fun: Callable[[History], bool]):
357
+ self.solve_condition = fun
358
+
359
+ # ===== private =====
360
+
361
+ def _should_solve(self, history):
362
+ return self.solve_condition(history)
363
+
364
+ def _y(self) -> TrialOutput:
365
+ out = TrialOutput()
366
+ for name, obj in self.objectives.items():
367
+ obj_result = ObjectiveResult(obj, self.fem)
368
+ out.update({name: obj_result})
369
+ return out
370
+
371
+ def _convert_y(self, y: TrialOutput) -> dict:
372
+ out = dict()
373
+ for name, result in y.items():
374
+ obj = self.objectives[name]
375
+ value_internal = obj.convert(result.value)
376
+ out.update({name: value_internal})
377
+ return out
378
+
379
+ def _hard_c(self, out: TrialConstraintOutput) -> TrialConstraintOutput:
380
+ for name, cns in self.constraints.items():
381
+ if cns.hard:
382
+ cns_result = ConstraintResult(cns, self.fem)
383
+ out.update({name: cns_result})
384
+ return out
385
+
386
+ def _soft_c(self, out: TrialConstraintOutput) -> TrialConstraintOutput:
387
+ for name, cns in self.constraints.items():
388
+ if not cns.hard:
389
+ cns_result = ConstraintResult(cns, self.fem)
390
+ out.update({name: cns_result})
391
+ return out
392
+
393
+ def _get_hard_constraint_violation_names(self, hard_c: TrialConstraintOutput) -> list[str]:
394
+ violation_names = []
395
+ for name, result in hard_c.items():
396
+ cns = self.constraints[name]
397
+ l_or_u = result.check_violation()
398
+ if l_or_u is not None:
399
+ logger.warning(_('----- Hard constraint violation! -----'))
400
+ logger.warning(_('constraint: {name}', name=name))
401
+ logger.warning(_('evaluated value: {value}', value=result.value))
402
+ if l_or_u == 'lower_bound':
403
+ logger.info(_('lower bound: {lb}', lb=cns.lower_bound))
404
+ violation_names.append(name + '_' + l_or_u)
405
+ elif l_or_u == 'upper_bound':
406
+ logger.info(_('upper bound: {ub}', ub=cns.upper_bound))
407
+ violation_names.append(name + '_' + l_or_u)
408
+ else:
409
+ raise NotImplementedError
410
+ return violation_names
411
+
412
+ def _check_and_raise_interruption(self) -> ...:
413
+ # raise Interrupt
414
+ interrupted = self.entire_status.value >= WorkerStatus.interrupting
415
+ if interrupted:
416
+ self.worker_status.value = WorkerStatus.interrupting
417
+ raise InterruptOptimization
418
+
419
+ # ===== solve =====
420
+
421
+ class _SolveSet:
422
+
423
+ opt: AbstractOptimizer
424
+ opt_: AbstractOptimizer
425
+
426
+ def __init__(self, opt: AbstractOptimizer):
427
+ self.opt: AbstractOptimizer = opt
428
+
429
+ def _preprocess(self):
430
+ pass
431
+
432
+ def _hard_constraint_handling(self, e: HardConstraintViolation):
433
+ pass
434
+
435
+ def _hidden_constraint_handling(self, e: _HiddenConstraintViolation):
436
+ pass
437
+
438
+ def _skip_handling(self, e: SkipSolve):
439
+ pass
440
+
441
+ def _if_succeeded(self, f_return: _FReturnValue):
442
+ pass
443
+
444
+ def _postprocess(self):
445
+ pass
446
+
447
+ def _solve_or_raise(
448
+ self,
449
+ opt_: AbstractOptimizer,
450
+ parameters: TrialInput,
451
+ variables_pass_to_fem: dict[str, SupportedVariableTypes],
452
+ history: History = None,
453
+ datetime_start=None,
454
+ ) -> _FReturnValue:
455
+
456
+ # create context
457
+ if history is not None:
458
+ record_to_history = history.recording(opt_.fem)
459
+ else:
460
+ class DummyRecordContext:
461
+ def __enter__(self):
462
+ return Record()
463
+
464
+ def __exit__(self, exc_type, exc_val, exc_tb):
465
+ pass
466
+
467
+ record_to_history = DummyRecordContext()
468
+
469
+ # processing with recording
470
+ with record_to_history as record:
471
+
472
+ # record common result
473
+ # input
474
+ record.x = parameters
475
+ # output (the value is nan, required for direction recording to graph)
476
+ record.y = TrialOutput(
477
+ {obj_name: ObjectiveResult(obj, opt_.fem, float('nan'))
478
+ for obj_name, obj in opt_.objectives.items()}
479
+ )
480
+ record.sub_fidelity_name = opt_.sub_fidelity_name
481
+ record.fidelity = opt_.fidelity
482
+ record.datetime_start = datetime_start
483
+ if self.opt._worker_name is not None:
484
+ record.messages.append(self.opt._worker_name)
485
+
486
+ # check skip
487
+ if not opt_._should_solve(history):
488
+ record.state = TrialState.skipped
489
+ raise SkipSolve
490
+
491
+ # start solve
492
+ if opt_.sub_fidelity_models != MAIN_FIDELITY_NAME:
493
+ logger.info(_('fidelity: ({name})', name=opt_.sub_fidelity_name))
494
+ logger.info(_('input variables:'))
495
+ logger.info(parameters)
496
+
497
+ # ===== update FEM parameter =====
498
+ logger.info(_('updating variables...'))
499
+ opt_.fem.update_parameter(variables_pass_to_fem)
500
+ opt_._check_and_raise_interruption()
501
+
502
+ # ===== evaluate hard constraint =====
503
+ logger.info(_('evaluating constraint functions...'))
504
+
505
+ hard_c = TrialConstraintOutput()
506
+ try:
507
+ opt_._hard_c(hard_c)
508
+
509
+ except _HiddenConstraintViolation as e:
510
+ _log_hidden_constraint(e)
511
+ record.c = hard_c
512
+ record.state = TrialState.get_corresponding_state_from_exception(e)
513
+ record.messages.append(
514
+ _('Hidden constraint violation '
515
+ 'during hard constraint function '
516
+ 'evaluation: ')
517
+ + create_err_msg_from_exception(e)
518
+ )
519
+
520
+ raise e
521
+
522
+ # check hard constraint violation
523
+ violation_names = opt_._get_hard_constraint_violation_names(hard_c)
524
+ if len(violation_names) > 0:
525
+ record.c = hard_c
526
+ record.state = TrialState.hard_constraint_violation
527
+ record.messages.append(
528
+ _('Hard constraint violation: ')
529
+ + ', '.join(violation_names))
530
+
531
+ raise HardConstraintViolation
532
+
533
+ # ===== update FEM =====
534
+ logger.info(_('Solving FEM...'))
535
+
536
+ try:
537
+ opt_.fem.update()
538
+ opt_._check_and_raise_interruption()
539
+
540
+ # if hidden constraint violation
541
+ except _HiddenConstraintViolation as e:
542
+
543
+ opt_._check_and_raise_interruption()
544
+
545
+ _log_hidden_constraint(e)
546
+ record.c = hard_c
547
+ record.state = TrialState.get_corresponding_state_from_exception(e)
548
+ record.messages.append(
549
+ _('Hidden constraint violation in FEM update: ')
550
+ + create_err_msg_from_exception(e))
551
+
552
+ raise e
553
+
554
+ # ===== evaluate y =====
555
+ logger.info(_('evaluating objective functions...'))
556
+
557
+ try:
558
+ y: TrialOutput = opt_._y()
559
+ opt_._check_and_raise_interruption()
560
+
561
+ # if intentional error (by user)
562
+ except _HiddenConstraintViolation as e:
563
+ opt_._check_and_raise_interruption()
564
+
565
+ _log_hidden_constraint(e)
566
+ record.c = hard_c
567
+ record.state = TrialState.get_corresponding_state_from_exception(e)
568
+ record.messages.append(
569
+ _('Hidden constraint violation during '
570
+ 'objective function evaluation: ')
571
+ + create_err_msg_from_exception(e))
572
+
573
+ raise e
574
+
575
+ # ===== evaluate soft constraint =====
576
+ logger.info(_('evaluating remaining constraints...'))
577
+
578
+ soft_c = TrialConstraintOutput()
579
+ try:
580
+ opt_._soft_c(soft_c)
581
+
582
+ # if intentional error (by user)
583
+ except _HiddenConstraintViolation as e:
584
+ _log_hidden_constraint(e)
585
+
586
+ _c = {}
587
+ _c.update(soft_c)
588
+ _c.update(hard_c)
589
+
590
+ record.y = y
591
+ record.c = _c
592
+ record.state = TrialState.get_corresponding_state_from_exception(e)
593
+ record.messages.append(
594
+ _('Hidden constraint violation during '
595
+ 'soft constraint function evaluation: ')
596
+ + create_err_msg_from_exception(e))
597
+
598
+ raise e
599
+
600
+ # ===== merge and sort constraints =====
601
+ c = TrialConstraintOutput()
602
+ c.update(soft_c)
603
+ c.update(hard_c)
604
+
605
+ # get values as minimize
606
+ y_internal: dict = opt_._convert_y(y)
607
+
608
+ logger.info(_('output:'))
609
+ logger.info(y)
610
+ record.y = y
611
+ record.c = c
612
+ record.state = TrialState.succeeded
613
+
614
+ opt_._check_and_raise_interruption()
615
+
616
+ return y, y_internal, c, record
617
+
618
+ def solve(
619
+ self,
620
+ x: TrialInput,
621
+ x_pass_to_fem_: dict[str, SupportedVariableTypes],
622
+ opt_: AbstractOptimizer | None = None,
623
+ ) -> _FReturnValue | None:
624
+
625
+ vm = self.opt.variable_manager
626
+
627
+ # opt_ はメインの opt 又は sub_fidelity
628
+ opt_ = opt_ or self.opt
629
+ self.opt_ = opt_
630
+
631
+ # check interruption
632
+ self.opt._check_and_raise_interruption()
633
+
634
+ # if opt_ is not self, update variable manager
635
+ opt_.variable_manager = vm
636
+
637
+ # preprocess
638
+ self._preprocess()
639
+
640
+ # declare output
641
+ f_return = None
642
+
643
+ # start solve
644
+ datetime_start = datetime.datetime.now()
645
+ try:
646
+ f_return = self._solve_or_raise(
647
+ opt_, x, x_pass_to_fem_, self.opt.history, datetime_start
648
+ )
649
+
650
+ except HardConstraintViolation as e:
651
+ self._hard_constraint_handling(e)
652
+
653
+ except _HiddenConstraintViolation as e:
654
+ self._hidden_constraint_handling(e)
655
+
656
+ except SkipSolve as e:
657
+ self._skip_handling(e)
658
+
659
+ else:
660
+ self._if_succeeded(f_return)
661
+
662
+ self._postprocess()
663
+
664
+ # check interruption
665
+ self.opt._check_and_raise_interruption()
666
+
667
+ return f_return
668
+
669
+ def _get_solve_set(self):
670
+ return self._SolveSet(self)
671
+
672
+ # ===== run and setup =====
673
+
674
+ def _setting_status(self):
675
+
676
+ # noinspection PyMethodParameters
677
+ class _SettingStatus:
678
+
679
+ def __enter__(self_):
680
+ pass
681
+
682
+ def __exit__(self_, exc_type, exc_val, exc_tb):
683
+ if exc_type is not None:
684
+ if self.worker_status.value < WorkerStatus.crashed:
685
+ self.worker_status.value = WorkerStatus.crashed
686
+ else:
687
+ if self.worker_status.value < WorkerStatus.finishing:
688
+ self.worker_status.value = WorkerStatus.finishing
689
+
690
+ return _SettingStatus()
691
+
692
+ def run(self) -> None:
693
+ raise NotImplementedError
694
+
695
+ def _run(
696
+ self,
697
+ worker_idx: int | str,
698
+ worker_name: str,
699
+ history: History,
700
+ entire_status: WorkerStatus,
701
+ worker_status: WorkerStatus,
702
+ worker_status_list: list[WorkerStatus],
703
+ wait_other_process_setup: bool,
704
+ ) -> None:
705
+
706
+ self.history = history
707
+ self.entire_status = entire_status
708
+ self.worker_status = worker_status
709
+ self._worker_index = worker_idx
710
+ self._worker_name = worker_name
711
+ self.worker_status_list = worker_status_list
712
+
713
+ class SettingStatusFinished:
714
+
715
+ # noinspection PyMethodParameters
716
+ def __enter__(self_):
717
+ pass
718
+
719
+ # noinspection PyMethodParameters
720
+ def __exit__(self_, exc_type, exc_val, exc_tb):
721
+ if exc_type is not None:
722
+ self.worker_status.value = WorkerStatus.crashed
723
+
724
+ import sys
725
+ from traceback import print_tb
726
+ print(
727
+ _(
728
+ '===== Exception raised in worker {worker_idx} =====',
729
+ worker_idx=worker_idx
730
+ ),
731
+ file=sys.stderr
732
+ )
733
+ print_tb(exc_tb)
734
+ print(
735
+ _(
736
+ '{name}: {exc_val}',
737
+ name=exc_type.__name__,
738
+ exc_val=exc_val
739
+ ),
740
+ file=sys.stderr
741
+ )
742
+
743
+ else:
744
+ self.worker_status.value = WorkerStatus.finished
745
+
746
+ logger.info(_(
747
+ en_message='worker `{worker}` started.',
748
+ worker=worker_name,
749
+ ))
750
+
751
+ with SettingStatusFinished():
752
+
753
+ self.worker_status.value = WorkerStatus.initializing
754
+
755
+ self.worker_status.value = WorkerStatus.launching_fem
756
+ self.fem._setup_after_parallel(self)
757
+
758
+ if wait_other_process_setup:
759
+ self.worker_status.value = WorkerStatus.waiting
760
+ while True:
761
+ self._check_and_raise_interruption()
762
+
763
+ # 他のすべての worker_status が wait 以上になったら break
764
+ logger.debug([ws.value for ws in worker_status_list])
765
+ if all([ws.value >= WorkerStatus.waiting
766
+ for ws in worker_status_list]):
767
+
768
+ # リソースの競合等を避けるため
769
+ # break する前に index 秒待つ
770
+ if isinstance(worker_idx, str):
771
+ wait_second = 0.
772
+ else:
773
+ wait_second = int(worker_idx + 1)
774
+ sleep(wait_second)
775
+ break
776
+
777
+ sleep(1)
778
+
779
+ self.worker_status.value = WorkerStatus.running
780
+
781
+ self.run()
782
+
783
+ logger.info(_(
784
+ en_message='worker `{worker}` successfully finished!',
785
+ worker=worker_name,
786
+ ))
787
+
788
+ def _logging(self):
789
+
790
+ # noinspection PyMethodParameters
791
+ class LoggingOutput:
792
+ def __enter__(self_):
793
+ self_.count = len(self.history.get_df()) + 1
794
+ logger.info(f'▼▼▼▼▼ solve {self_.count} start ▼▼▼▼▼')
795
+
796
+ def __exit__(self_, exc_type, exc_val, exc_tb):
797
+ logger.info(f'▲▲▲▲▲ solve {self_.count} end ▲▲▲▲▲\n')
798
+
799
+ return LoggingOutput()
800
+
801
+ def _load_problem_from_fem(self):
802
+ if self.fem._load_problem_from_fem and not self._done_load_problem_from_fem:
803
+ self.fem.load_variables(self)
804
+ self.fem.load_objectives(self)
805
+ self.fem.load_constraints(self)
806
+ self._done_load_problem_from_fem = True
807
+
808
+ # noinspection PyMethodMayBeStatic
809
+ def _get_additional_data(self) -> dict:
810
+ return dict()
811
+
812
+ def _collect_additional_data(self) -> dict:
813
+ additional_data = {}
814
+ additional_data.update(self._get_additional_data())
815
+ additional_data.update(self.fem._get_additional_data())
816
+ return additional_data
817
+
818
+ def _finalize_history(self):
819
+ if not self.history._finalized:
820
+ parameters = self.variable_manager.get_variables(
821
+ filter='parameter', format='raw'
822
+ )
823
+ self.history.finalize(
824
+ parameters,
825
+ list(self.objectives.keys()),
826
+ list(self.constraints.keys()),
827
+ [self.sub_fidelity_name] + list(self.sub_fidelity_models.keys()),
828
+ additional_data=self._collect_additional_data()
829
+ )
830
+
831
+ def _setup_before_parallel(self):
832
+
833
+ if not self._done_setup_before_parallel:
834
+
835
+ # check compatibility with fem if needed
836
+ variables = self.variable_manager.get_variables()
837
+ for var_name, variable in variables.items():
838
+ if variable.pass_to_fem:
839
+ self.fem._check_param_and_raise(var_name)
840
+
841
+ # resolve evaluation order
842
+ self.variable_manager.resolve()
843
+
844
+ self._done_setup_before_parallel = True
845
+
846
+ def _setup_after_parallel(self):
847
+ pass
848
+
849
+ def _finalize(self):
850
+
851
+ # check sub fidelity models
852
+ if self.sub_fidelity_models is None:
853
+ self.sub_fidelity_models = SubFidelityModels()
854
+ for sub_fidelity_model in self.sub_fidelity_models.values():
855
+ assert sub_fidelity_model.objectives.keys() == self.objectives.keys()
856
+ assert sub_fidelity_model.constraints.keys() == self.constraints.keys()
857
+
858
+ # finalize
859
+ self._load_problem_from_fem()
860
+ self._finalize_history()
861
+
862
+ # setup if needed
863
+ self._setup_before_parallel()
864
+ self._setup_after_parallel()
865
+
866
+
867
+ class SubFidelityModel(AbstractOptimizer):
868
+ pass
869
+
870
+
871
+ class SubFidelityModels(dict[str, SubFidelityModel]):
872
+
873
+ def _update(self, name, model: SubFidelityModel, fidelity: Fidelity):
874
+ model.sub_fidelity_name = name
875
+ model.fidelity = fidelity
876
+ self.update({name: model})