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

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

Potentially problematic release.


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

Files changed (272) hide show
  1. pyfemtet/__init__.py +6 -1
  2. pyfemtet/_i18n/1. make_pot_and_update_po.bat +8 -0
  3. pyfemtet/_i18n/2. build_mo.bat +5 -0
  4. pyfemtet/_i18n/__init__.py +4 -0
  5. pyfemtet/_i18n/babel.cfg +2 -0
  6. pyfemtet/_i18n/i18n.py +37 -0
  7. pyfemtet/_i18n/locales/ja/LC_MESSAGES/messages.mo +0 -0
  8. pyfemtet/_i18n/locales/ja/LC_MESSAGES/messages.po +1020 -0
  9. pyfemtet/_i18n/locales/messages.pot +987 -0
  10. pyfemtet/{_message → _i18n}/messages.py +128 -41
  11. pyfemtet/_util/closing.py +19 -0
  12. pyfemtet/_util/dask_util.py +89 -7
  13. pyfemtet/_util/df_util.py +29 -0
  14. pyfemtet/_util/excel_macro_util.py +8 -3
  15. pyfemtet/_util/excel_parse_util.py +43 -23
  16. pyfemtet/_util/femtet_access_inspection.py +120 -0
  17. pyfemtet/{_femtet_config_util/autosave.py → _util/femtet_autosave.py} +7 -0
  18. pyfemtet/_util/femtet_exit.py +105 -0
  19. pyfemtet/_util/femtet_version.py +20 -0
  20. pyfemtet/_util/helper.py +94 -0
  21. pyfemtet/_util/process_util.py +107 -0
  22. pyfemtet/_util/str_enum.py +44 -0
  23. pyfemtet/core.py +15 -47
  24. pyfemtet/dispatch_extensions/__init__.py +8 -11
  25. pyfemtet/dispatch_extensions/_impl.py +42 -198
  26. pyfemtet/logger/__init__.py +8 -1
  27. pyfemtet/logger/_impl.py +5 -6
  28. pyfemtet/opt/__init__.py +3 -17
  29. pyfemtet/opt/exceptions.py +45 -0
  30. pyfemtet/opt/femopt.py +608 -0
  31. pyfemtet/opt/history/__init__.py +11 -0
  32. pyfemtet/opt/history/_history.py +1404 -0
  33. pyfemtet/opt/history/_hypervolume.py +169 -0
  34. pyfemtet/opt/history/_optimality.py +79 -0
  35. pyfemtet/opt/interface/__init__.py +17 -24
  36. pyfemtet/opt/interface/_base_interface.py +222 -0
  37. pyfemtet/opt/interface/_excel_interface/__init__.py +3 -0
  38. pyfemtet/opt/interface/_excel_interface/debug-excel-interface.xlsm +0 -0
  39. pyfemtet/opt/interface/_excel_interface/excel_interface.py +999 -0
  40. pyfemtet/opt/interface/_femtet_interface/__init__.py +3 -0
  41. pyfemtet/opt/interface/{_femtet_parametric.py → _femtet_interface/_femtet_parametric.py} +20 -12
  42. pyfemtet/opt/interface/{_femtet.py → _femtet_interface/femtet_interface.py} +505 -349
  43. pyfemtet/opt/interface/_femtet_with_nx_interface/__init__.py +5 -0
  44. pyfemtet/opt/interface/_femtet_with_nx_interface/femtet_with_nx_interface.py +230 -0
  45. pyfemtet/opt/interface/_femtet_with_nx_interface/model1.prt +0 -0
  46. pyfemtet/opt/interface/_femtet_with_nx_interface/model1.x_t +98 -0
  47. pyfemtet/opt/interface/{_femtet_with_nx → _femtet_with_nx_interface}/update_model.py +1 -3
  48. pyfemtet/opt/interface/_femtet_with_solidworks/__init__.py +5 -0
  49. pyfemtet/opt/interface/_femtet_with_solidworks/femtet_with_solidworks_interface.py +122 -0
  50. pyfemtet/opt/interface/_solidworks_interface/__init__.py +5 -0
  51. pyfemtet/opt/interface/_solidworks_interface/solidworks_interface.py +206 -0
  52. pyfemtet/opt/interface/_surrogate_model_interface/__init__.py +8 -0
  53. pyfemtet/opt/interface/_surrogate_model_interface/base_surrogate_interface.py +150 -0
  54. pyfemtet/opt/interface/_surrogate_model_interface/botorch_interface.py +298 -0
  55. pyfemtet/opt/interface/_surrogate_model_interface/debug-pof-botorch.reccsv +18 -0
  56. pyfemtet/opt/interface/_with_excel_settings/__init__.py +61 -0
  57. pyfemtet/opt/interface/_with_excel_settings/with_excel_settings.py +134 -0
  58. pyfemtet/opt/meta_script/YAML_Generator.xlsm +0 -0
  59. pyfemtet/opt/meta_script/__main__.py +58 -36
  60. pyfemtet/opt/optimizer/__init__.py +7 -9
  61. pyfemtet/opt/optimizer/_base_optimizer.py +885 -0
  62. pyfemtet/opt/optimizer/optuna_optimizer/__init__.py +9 -0
  63. pyfemtet/opt/optimizer/optuna_optimizer/_optuna_attribute.py +73 -0
  64. pyfemtet/opt/optimizer/optuna_optimizer/_optuna_optimizer.py +678 -0
  65. pyfemtet/opt/optimizer/optuna_optimizer/_pof_botorch/__init__.py +7 -0
  66. pyfemtet/opt/optimizer/optuna_optimizer/_pof_botorch/debug-pof-botorch.reccsv +18 -0
  67. pyfemtet/opt/optimizer/optuna_optimizer/_pof_botorch/enable_nonlinear_constraint.py +244 -0
  68. pyfemtet/opt/optimizer/optuna_optimizer/_pof_botorch/pof_botorch_sampler.py +1249 -0
  69. pyfemtet/opt/optimizer/optuna_optimizer/wat_ex14_parametric_jp.femprj +0 -0
  70. pyfemtet/opt/optimizer/scipy_optimizer/__init__.py +1 -0
  71. pyfemtet/opt/optimizer/scipy_optimizer/_scipy_optimizer.py +364 -0
  72. pyfemtet/opt/prediction/__init__.py +7 -0
  73. pyfemtet/opt/prediction/_botorch_utils.py +133 -0
  74. pyfemtet/opt/prediction/_gpytorch_modules_extension.py +142 -0
  75. pyfemtet/opt/prediction/_helper.py +155 -0
  76. pyfemtet/opt/prediction/_model.py +118 -0
  77. pyfemtet/opt/problem/problem.py +304 -0
  78. pyfemtet/opt/problem/variable_manager/__init__.py +20 -0
  79. pyfemtet/opt/problem/variable_manager/_string_as_expression.py +115 -0
  80. pyfemtet/opt/problem/variable_manager/_variable_manager.py +295 -0
  81. pyfemtet/opt/visualization/history_viewer/__main__.py +5 -0
  82. pyfemtet/opt/visualization/{_base.py → history_viewer/_base_application.py} +18 -13
  83. pyfemtet/opt/visualization/history_viewer/_common_pages.py +150 -0
  84. pyfemtet/opt/visualization/{_complex_components → history_viewer/_complex_components}/alert_region.py +10 -5
  85. pyfemtet/opt/visualization/{_complex_components → history_viewer/_complex_components}/control_femtet.py +16 -13
  86. pyfemtet/opt/visualization/{_complex_components → history_viewer/_complex_components}/main_graph.py +117 -47
  87. pyfemtet/opt/visualization/{_complex_components → history_viewer/_complex_components}/pm_graph.py +159 -138
  88. pyfemtet/opt/visualization/history_viewer/_process_monitor/_application.py +173 -0
  89. pyfemtet/opt/visualization/history_viewer/_process_monitor/_pages.py +291 -0
  90. pyfemtet/opt/visualization/{_wrapped_components → history_viewer/_wrapped_components}/dbc.py +1 -1
  91. pyfemtet/opt/visualization/{_wrapped_components → history_viewer/_wrapped_components}/dcc.py +1 -1
  92. pyfemtet/opt/visualization/{_wrapped_components → history_viewer/_wrapped_components}/html.py +1 -1
  93. pyfemtet/opt/visualization/history_viewer/result_viewer/__main__.py +5 -0
  94. pyfemtet/opt/visualization/{result_viewer/application.py → history_viewer/result_viewer/_application.py} +6 -6
  95. pyfemtet/opt/visualization/{result_viewer/pages.py → history_viewer/result_viewer/_pages.py} +106 -82
  96. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08.csv +18 -0
  97. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08.db +0 -0
  98. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8.jpg +0 -0
  99. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8.log +45 -0
  100. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8.pdt +0 -0
  101. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_1.jpg +0 -0
  102. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_1.pdt +0 -0
  103. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_10.jpg +0 -0
  104. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_10.pdt +0 -0
  105. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_11.jpg +0 -0
  106. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_11.pdt +0 -0
  107. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_12.jpg +0 -0
  108. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_12.pdt +0 -0
  109. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_13.jpg +0 -0
  110. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_13.pdt +0 -0
  111. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_14.jpg +0 -0
  112. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_14.pdt +0 -0
  113. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_15.jpg +0 -0
  114. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_15.pdt +0 -0
  115. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_16.jpg +0 -0
  116. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_16.pdt +0 -0
  117. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_17.jpg +0 -0
  118. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_17.pdt +0 -0
  119. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_18.jpg +0 -0
  120. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_18.pdt +0 -0
  121. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_19.jpg +0 -0
  122. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_19.pdt +0 -0
  123. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_2.jpg +0 -0
  124. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_2.pdt +0 -0
  125. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_20.jpg +0 -0
  126. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_20.pdt +0 -0
  127. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_3.jpg +0 -0
  128. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_3.pdt +0 -0
  129. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_4.bgr +0 -0
  130. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_4.bnd +0 -0
  131. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_4.btr +0 -0
  132. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_4.jpg +0 -0
  133. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_4.mtl +0 -0
  134. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_4.pdt +0 -0
  135. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_4.prm +0 -0
  136. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_5.jpg +0 -0
  137. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_5.pdt +0 -0
  138. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_6.jpg +0 -0
  139. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_6.pdt +0 -0
  140. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_7.jpg +0 -0
  141. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_7.pdt +0 -0
  142. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_8.jpg +0 -0
  143. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_8.pdt +0 -0
  144. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_9.jpg +0 -0
  145. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.Results/ex8_trial_9.pdt +0 -0
  146. pyfemtet/opt/visualization/history_viewer/result_viewer/tutorial_files/tutorial_gau_ex08_parametric.femprj +0 -0
  147. pyfemtet/opt/visualization/plotter/main_figure_creator.py +536 -0
  148. pyfemtet/opt/visualization/plotter/pm_graph_creator.py +359 -0
  149. pyfemtet/opt/worker_status.py +120 -0
  150. {pyfemtet-0.9.5.dist-info → pyfemtet-1.0.0b0.dist-info}/METADATA +23 -24
  151. pyfemtet-1.0.0b0.dist-info/RECORD +172 -0
  152. pyfemtet-1.0.0b0.dist-info/entry_points.txt +3 -0
  153. pyfemtet/_femtet_config_util/exit.py +0 -59
  154. pyfemtet/_message/1. make_pot.bat +0 -11
  155. pyfemtet/_message/2. make_mo.bat +0 -6
  156. pyfemtet/_message/__init__.py +0 -5
  157. pyfemtet/_message/babel.cfg +0 -2
  158. pyfemtet/_message/locales/ja/LC_MESSAGES/messages.mo +0 -0
  159. pyfemtet/_message/locales/ja/LC_MESSAGES/messages.po +0 -570
  160. pyfemtet/_message/locales/messages.pot +0 -551
  161. pyfemtet/_warning.py +0 -87
  162. pyfemtet/brep/_impl.py +0 -18
  163. pyfemtet/opt/_femopt.py +0 -1007
  164. pyfemtet/opt/_femopt_core.py +0 -1169
  165. pyfemtet/opt/_test_utils/control_femtet.py +0 -39
  166. pyfemtet/opt/_test_utils/hyper_sphere.py +0 -24
  167. pyfemtet/opt/_test_utils/record_history.py +0 -130
  168. pyfemtet/opt/advanced_samples/excel_ui/(ref) original_project.femprj +0 -0
  169. pyfemtet/opt/advanced_samples/excel_ui/femtet-macro.xlsm +0 -0
  170. pyfemtet/opt/advanced_samples/excel_ui/pyfemtet-core.py +0 -291
  171. pyfemtet/opt/advanced_samples/excel_ui/test-pyfemtet-core.cmd +0 -22
  172. pyfemtet/opt/advanced_samples/restart/gal_ex13_parametric.femprj +0 -0
  173. pyfemtet/opt/advanced_samples/restart/gal_ex13_parametric_restart.py +0 -99
  174. pyfemtet/opt/advanced_samples/restart/gal_ex13_parametric_restart_jp.py +0 -102
  175. pyfemtet/opt/advanced_samples/surrogate_model/gal_ex13_create_training_data.py +0 -60
  176. pyfemtet/opt/advanced_samples/surrogate_model/gal_ex13_create_training_data_jp.py +0 -57
  177. pyfemtet/opt/advanced_samples/surrogate_model/gal_ex13_optimize_with_surrogate.py +0 -100
  178. pyfemtet/opt/advanced_samples/surrogate_model/gal_ex13_optimize_with_surrogate_jp.py +0 -90
  179. pyfemtet/opt/advanced_samples/surrogate_model/gal_ex13_parametric.femprj +0 -0
  180. pyfemtet/opt/interface/_base.py +0 -101
  181. pyfemtet/opt/interface/_excel_interface.py +0 -984
  182. pyfemtet/opt/interface/_femtet_excel.py +0 -141
  183. pyfemtet/opt/interface/_femtet_with_nx/__init__.py +0 -3
  184. pyfemtet/opt/interface/_femtet_with_nx/_interface.py +0 -178
  185. pyfemtet/opt/interface/_femtet_with_sldworks.py +0 -298
  186. pyfemtet/opt/interface/_surrogate/__init__.py +0 -5
  187. pyfemtet/opt/interface/_surrogate/_base.py +0 -129
  188. pyfemtet/opt/interface/_surrogate/_chaospy.py +0 -71
  189. pyfemtet/opt/interface/_surrogate/_singletaskgp.py +0 -71
  190. pyfemtet/opt/interface/_surrogate_excel.py +0 -102
  191. pyfemtet/opt/optimizer/_base.py +0 -376
  192. pyfemtet/opt/optimizer/_optuna/_botorch_patch/enable_nonlinear_constraint.py +0 -220
  193. pyfemtet/opt/optimizer/_optuna/_optuna.py +0 -434
  194. pyfemtet/opt/optimizer/_optuna/_pof_botorch.py +0 -1914
  195. pyfemtet/opt/optimizer/_scipy.py +0 -159
  196. pyfemtet/opt/optimizer/_scipy_scalar.py +0 -127
  197. pyfemtet/opt/optimizer/parameter.py +0 -113
  198. pyfemtet/opt/prediction/_base.py +0 -61
  199. pyfemtet/opt/prediction/single_task_gp.py +0 -119
  200. pyfemtet/opt/samples/femprj_sample/ParametricIF.femprj +0 -0
  201. pyfemtet/opt/samples/femprj_sample/ParametricIF.py +0 -29
  202. pyfemtet/opt/samples/femprj_sample/ParametricIF_test_result.reccsv +0 -13
  203. pyfemtet/opt/samples/femprj_sample/cad_ex01_NX.femprj +0 -0
  204. pyfemtet/opt/samples/femprj_sample/cad_ex01_NX.prt +0 -0
  205. pyfemtet/opt/samples/femprj_sample/cad_ex01_NX.py +0 -135
  206. pyfemtet/opt/samples/femprj_sample/cad_ex01_NX_test_result.reccsv +0 -23
  207. pyfemtet/opt/samples/femprj_sample/cad_ex01_SW.SLDPRT +0 -0
  208. pyfemtet/opt/samples/femprj_sample/cad_ex01_SW.femprj +0 -0
  209. pyfemtet/opt/samples/femprj_sample/cad_ex01_SW.py +0 -131
  210. pyfemtet/opt/samples/femprj_sample/cad_ex01_SW_test_result.reccsv +0 -23
  211. pyfemtet/opt/samples/femprj_sample/constrained_pipe.femprj +0 -0
  212. pyfemtet/opt/samples/femprj_sample/constrained_pipe.py +0 -96
  213. pyfemtet/opt/samples/femprj_sample/constrained_pipe_test_result.reccsv +0 -13
  214. pyfemtet/opt/samples/femprj_sample/gal_ex58_parametric.femprj +0 -0
  215. pyfemtet/opt/samples/femprj_sample/gal_ex58_parametric.py +0 -74
  216. pyfemtet/opt/samples/femprj_sample/gal_ex58_parametric_test_result.reccsv +0 -13
  217. pyfemtet/opt/samples/femprj_sample/gau_ex08_parametric.femprj +0 -0
  218. pyfemtet/opt/samples/femprj_sample/gau_ex08_parametric.py +0 -58
  219. pyfemtet/opt/samples/femprj_sample/gau_ex08_parametric_test_result.reccsv +0 -23
  220. pyfemtet/opt/samples/femprj_sample/gau_ex12_parametric.femprj +0 -0
  221. pyfemtet/opt/samples/femprj_sample/gau_ex12_parametric.py +0 -52
  222. pyfemtet/opt/samples/femprj_sample/her_ex40_parametric.femprj +0 -0
  223. pyfemtet/opt/samples/femprj_sample/her_ex40_parametric.py +0 -138
  224. pyfemtet/opt/samples/femprj_sample/her_ex40_parametric_test_result.reccsv +0 -18
  225. pyfemtet/opt/samples/femprj_sample/paswat_ex1_parametric.femprj +0 -0
  226. pyfemtet/opt/samples/femprj_sample/paswat_ex1_parametric.py +0 -60
  227. pyfemtet/opt/samples/femprj_sample/paswat_ex1_parametric_parallel.py +0 -61
  228. pyfemtet/opt/samples/femprj_sample/paswat_ex1_parametric_test_result.reccsv +0 -18
  229. pyfemtet/opt/samples/femprj_sample/wat_ex14_parametric.femprj +0 -0
  230. pyfemtet/opt/samples/femprj_sample/wat_ex14_parametric.py +0 -58
  231. pyfemtet/opt/samples/femprj_sample/wat_ex14_parametric_parallel.py +0 -58
  232. pyfemtet/opt/samples/femprj_sample/wat_ex14_parametric_test_result.reccsv +0 -18
  233. pyfemtet/opt/samples/femprj_sample_jp/ParametricIF_jp.femprj +0 -0
  234. pyfemtet/opt/samples/femprj_sample_jp/ParametricIF_jp.py +0 -29
  235. pyfemtet/opt/samples/femprj_sample_jp/cad_ex01_NX_jp.femprj +0 -0
  236. pyfemtet/opt/samples/femprj_sample_jp/cad_ex01_NX_jp.py +0 -129
  237. pyfemtet/opt/samples/femprj_sample_jp/cad_ex01_SW_jp.femprj +0 -0
  238. pyfemtet/opt/samples/femprj_sample_jp/cad_ex01_SW_jp.py +0 -125
  239. pyfemtet/opt/samples/femprj_sample_jp/constrained_pipe_jp.py +0 -93
  240. pyfemtet/opt/samples/femprj_sample_jp/gal_ex58_parametric_jp.femprj +0 -0
  241. pyfemtet/opt/samples/femprj_sample_jp/gal_ex58_parametric_jp.py +0 -70
  242. pyfemtet/opt/samples/femprj_sample_jp/gau_ex08_parametric_jp.femprj +0 -0
  243. pyfemtet/opt/samples/femprj_sample_jp/gau_ex08_parametric_jp.py +0 -57
  244. pyfemtet/opt/samples/femprj_sample_jp/gau_ex12_parametric_jp.py +0 -52
  245. pyfemtet/opt/samples/femprj_sample_jp/her_ex40_parametric_jp.femprj +0 -0
  246. pyfemtet/opt/samples/femprj_sample_jp/her_ex40_parametric_jp.py +0 -138
  247. pyfemtet/opt/samples/femprj_sample_jp/paswat_ex1_parametric_jp.femprj +0 -0
  248. pyfemtet/opt/samples/femprj_sample_jp/paswat_ex1_parametric_jp.py +0 -58
  249. pyfemtet/opt/samples/femprj_sample_jp/paswat_ex1_parametric_parallel_jp.py +0 -59
  250. pyfemtet/opt/samples/femprj_sample_jp/wat_ex14_parametric_jp.py +0 -56
  251. pyfemtet/opt/samples/femprj_sample_jp/wat_ex14_parametric_parallel_jp.py +0 -56
  252. pyfemtet/opt/visualization/_complex_components/main_figure_creator.py +0 -332
  253. pyfemtet/opt/visualization/_complex_components/pm_graph_creator.py +0 -201
  254. pyfemtet/opt/visualization/_process_monitor/application.py +0 -226
  255. pyfemtet/opt/visualization/_process_monitor/pages.py +0 -406
  256. pyfemtet/opt/visualization/_wrapped_components/__init__.py +0 -0
  257. pyfemtet/opt/visualization/result_viewer/__init__.py +0 -0
  258. pyfemtet-0.9.5.dist-info/RECORD +0 -158
  259. pyfemtet-0.9.5.dist-info/entry_points.txt +0 -3
  260. /pyfemtet/{_femtet_config_util → opt/problem}/__init__.py +0 -0
  261. /pyfemtet/{brep → opt/visualization/history_viewer}/__init__.py +0 -0
  262. /pyfemtet/opt/{_test_utils → visualization/history_viewer/_complex_components}/__init__.py +0 -0
  263. /pyfemtet/opt/{optimizer/_optuna → visualization/history_viewer/_process_monitor}/__init__.py +0 -0
  264. /pyfemtet/opt/{optimizer/_optuna/_botorch_patch → visualization/history_viewer/_wrapped_components}/__init__.py +0 -0
  265. /pyfemtet/opt/visualization/{_wrapped_components → history_viewer/_wrapped_components}/str_enum.py +0 -0
  266. /pyfemtet/opt/visualization/{result_viewer → history_viewer/result_viewer}/.gitignore +0 -0
  267. /pyfemtet/opt/visualization/{_complex_components → history_viewer/result_viewer}/__init__.py +0 -0
  268. /pyfemtet/opt/visualization/{_process_monitor → plotter}/__init__.py +0 -0
  269. /pyfemtet/opt/{samples/femprj_sample_jp/wat_ex14_parametric_jp.femprj → wat_ex14_parametric_jp.femprj} +0 -0
  270. {pyfemtet-0.9.5.dist-info → pyfemtet-1.0.0b0.dist-info}/LICENSE +0 -0
  271. {pyfemtet-0.9.5.dist-info → pyfemtet-1.0.0b0.dist-info}/LICENSE_THIRD_PARTY.txt +0 -0
  272. {pyfemtet-0.9.5.dist-info → pyfemtet-1.0.0b0.dist-info}/WHEEL +0 -0
@@ -0,0 +1,885 @@
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
+
438
+ def _preprocess(self):
439
+ pass
440
+
441
+ def _hard_constraint_handling(self, e: HardConstraintViolation):
442
+ pass
443
+
444
+ def _hidden_constraint_handling(self, e: _HiddenConstraintViolation):
445
+ pass
446
+
447
+ def _skip_handling(self, e: SkipSolve):
448
+ pass
449
+
450
+ def _if_succeeded(self, f_return: _FReturnValue):
451
+ pass
452
+
453
+ def _postprocess(self):
454
+ pass
455
+
456
+ def _solve_or_raise(
457
+ self,
458
+ opt_: AbstractOptimizer,
459
+ parameters: TrialInput,
460
+ variables_pass_to_fem: dict[str, SupportedVariableTypes],
461
+ history: History = None,
462
+ datetime_start=None,
463
+ ) -> _FReturnValue:
464
+
465
+ # create context
466
+ if history is not None:
467
+ record_to_history = history.recording(opt_.fem)
468
+ else:
469
+ class DummyRecordContext:
470
+ def __enter__(self):
471
+ return Record()
472
+
473
+ def __exit__(self, exc_type, exc_val, exc_tb):
474
+ pass
475
+
476
+ record_to_history = DummyRecordContext()
477
+
478
+ # processing with recording
479
+ with record_to_history as record:
480
+
481
+ # record common result
482
+ # input
483
+ record.x = parameters
484
+ # output (the value is nan, required for direction recording to graph)
485
+ record.y = TrialOutput(
486
+ {obj_name: ObjectiveResult(obj, opt_.fem, float('nan'))
487
+ for obj_name, obj in opt_.objectives.items()}
488
+ )
489
+ record.sub_fidelity_name = opt_.sub_fidelity_name
490
+ record.fidelity = opt_.fidelity
491
+ record.datetime_start = datetime_start
492
+ if self.opt._worker_name is not None:
493
+ record.messages.append(self.opt._worker_name)
494
+
495
+ # check skip
496
+ if not opt_._should_solve(history):
497
+ record.state = TrialState.skipped
498
+ raise SkipSolve
499
+
500
+ # start solve
501
+ if opt_.sub_fidelity_models != MAIN_FIDELITY_NAME:
502
+ logger.info(_('fidelity: ({name})', name=opt_.sub_fidelity_name))
503
+ logger.info(_('input variables:'))
504
+ logger.info(parameters)
505
+
506
+ # ===== update FEM parameter =====
507
+ logger.info(_('updating variables...'))
508
+ opt_.fem.update_parameter(variables_pass_to_fem)
509
+ opt_._check_and_raise_interruption()
510
+
511
+ # ===== evaluate hard constraint =====
512
+ logger.info(_('evaluating constraint functions...'))
513
+
514
+ hard_c = TrialConstraintOutput()
515
+ try:
516
+ opt_._hard_c(hard_c)
517
+
518
+ except _HiddenConstraintViolation as e:
519
+ _log_hidden_constraint(e)
520
+ record.c = hard_c
521
+ record.state = TrialState.get_corresponding_state_from_exception(e)
522
+ record.messages.append(
523
+ _('Hidden constraint violation '
524
+ 'during hard constraint function '
525
+ 'evaluation: ')
526
+ + create_err_msg_from_exception(e)
527
+ )
528
+
529
+ raise e
530
+
531
+ # check hard constraint violation
532
+ violation_names = opt_._get_hard_constraint_violation_names(hard_c)
533
+ if len(violation_names) > 0:
534
+ record.c = hard_c
535
+ record.state = TrialState.hard_constraint_violation
536
+ record.messages.append(
537
+ _('Hard constraint violation: ')
538
+ + ', '.join(violation_names))
539
+
540
+ raise HardConstraintViolation
541
+
542
+ # ===== update FEM =====
543
+ logger.info(_('Solving FEM...'))
544
+
545
+ try:
546
+ opt_.fem.update()
547
+ opt_._check_and_raise_interruption()
548
+
549
+ # if hidden constraint violation
550
+ except _HiddenConstraintViolation as e:
551
+
552
+ opt_._check_and_raise_interruption()
553
+
554
+ _log_hidden_constraint(e)
555
+ record.c = hard_c
556
+ record.state = TrialState.get_corresponding_state_from_exception(e)
557
+ record.messages.append(
558
+ _('Hidden constraint violation in FEM update: ')
559
+ + create_err_msg_from_exception(e))
560
+
561
+ raise e
562
+
563
+ # ===== evaluate y =====
564
+ logger.info(_('evaluating objective functions...'))
565
+
566
+ try:
567
+ y: TrialOutput = opt_._y()
568
+ opt_._check_and_raise_interruption()
569
+
570
+ # if intentional error (by user)
571
+ except _HiddenConstraintViolation as e:
572
+ opt_._check_and_raise_interruption()
573
+
574
+ _log_hidden_constraint(e)
575
+ record.c = hard_c
576
+ record.state = TrialState.get_corresponding_state_from_exception(e)
577
+ record.messages.append(
578
+ _('Hidden constraint violation during '
579
+ 'objective function evaluation: ')
580
+ + create_err_msg_from_exception(e))
581
+
582
+ raise e
583
+
584
+ # ===== evaluate soft constraint =====
585
+ logger.info(_('evaluating remaining constraints...'))
586
+
587
+ soft_c = TrialConstraintOutput()
588
+ try:
589
+ opt_._soft_c(soft_c)
590
+
591
+ # if intentional error (by user)
592
+ except _HiddenConstraintViolation as e:
593
+ _log_hidden_constraint(e)
594
+
595
+ _c = {}
596
+ _c.update(soft_c)
597
+ _c.update(hard_c)
598
+
599
+ record.y = y
600
+ record.c = _c
601
+ record.state = TrialState.get_corresponding_state_from_exception(e)
602
+ record.messages.append(
603
+ _('Hidden constraint violation during '
604
+ 'soft constraint function evaluation: ')
605
+ + create_err_msg_from_exception(e))
606
+
607
+ raise e
608
+
609
+ # ===== merge and sort constraints =====
610
+ c = TrialConstraintOutput()
611
+ c.update(soft_c)
612
+ c.update(hard_c)
613
+
614
+ # get values as minimize
615
+ y_internal: dict = opt_._convert_y(y)
616
+
617
+ logger.info(_('output:'))
618
+ logger.info(y)
619
+ record.y = y
620
+ record.c = c
621
+ record.state = TrialState.succeeded
622
+
623
+ opt_._check_and_raise_interruption()
624
+
625
+ return y, y_internal, c, record
626
+
627
+ def solve(
628
+ self,
629
+ x: TrialInput,
630
+ x_pass_to_fem_: dict[str, SupportedVariableTypes],
631
+ opt_: AbstractOptimizer | None = None,
632
+ ) -> _FReturnValue | None:
633
+
634
+ vm = self.opt.variable_manager
635
+
636
+ # opt_ はメインの opt 又は sub_fidelity
637
+ opt_ = opt_ or self.opt
638
+ self.opt_ = opt_
639
+
640
+ # check interruption
641
+ self.opt._check_and_raise_interruption()
642
+
643
+ # if opt_ is not self, update variable manager
644
+ opt_.variable_manager = vm
645
+
646
+ # preprocess
647
+ self._preprocess()
648
+
649
+ # declare output
650
+ f_return = None
651
+
652
+ # start solve
653
+ datetime_start = datetime.datetime.now()
654
+ try:
655
+ f_return = self._solve_or_raise(
656
+ opt_, x, x_pass_to_fem_, self.opt.history, datetime_start
657
+ )
658
+
659
+ except HardConstraintViolation as e:
660
+ self._hard_constraint_handling(e)
661
+
662
+ except _HiddenConstraintViolation as e:
663
+ self._hidden_constraint_handling(e)
664
+
665
+ except SkipSolve as e:
666
+ self._skip_handling(e)
667
+
668
+ else:
669
+ self._if_succeeded(f_return)
670
+
671
+ self._postprocess()
672
+
673
+ # check interruption
674
+ self.opt._check_and_raise_interruption()
675
+
676
+ return f_return
677
+
678
+ def _get_solve_set(self):
679
+ return self._SolveSet(self)
680
+
681
+ # ===== run and setup =====
682
+
683
+ def _setting_status(self):
684
+
685
+ # noinspection PyMethodParameters
686
+ class _SettingStatus:
687
+
688
+ def __enter__(self_):
689
+ pass
690
+
691
+ def __exit__(self_, exc_type, exc_val, exc_tb):
692
+ if exc_type is not None:
693
+ if self.worker_status.value < WorkerStatus.crashed:
694
+ self.worker_status.value = WorkerStatus.crashed
695
+ else:
696
+ if self.worker_status.value < WorkerStatus.finishing:
697
+ self.worker_status.value = WorkerStatus.finishing
698
+
699
+ return _SettingStatus()
700
+
701
+ def run(self) -> None:
702
+ raise NotImplementedError
703
+
704
+ def _run(
705
+ self,
706
+ worker_idx: int | str,
707
+ worker_name: str,
708
+ history: History,
709
+ entire_status: WorkerStatus,
710
+ worker_status: WorkerStatus,
711
+ worker_status_list: list[WorkerStatus],
712
+ wait_other_process_setup: bool,
713
+ ) -> None:
714
+
715
+ self.history = history
716
+ self.entire_status = entire_status
717
+ self.worker_status = worker_status
718
+ self._worker_index = worker_idx
719
+ self._worker_name = worker_name
720
+ self.worker_status_list = worker_status_list
721
+
722
+ class SettingStatusFinished:
723
+
724
+ # noinspection PyMethodParameters
725
+ def __enter__(self_):
726
+ pass
727
+
728
+ # noinspection PyMethodParameters
729
+ def __exit__(self_, exc_type, exc_val, exc_tb):
730
+ if exc_type is not None:
731
+ self.worker_status.value = WorkerStatus.crashed
732
+
733
+ import sys
734
+ from traceback import print_tb
735
+ print(
736
+ _(
737
+ '===== Exception raised in worker {worker_idx} =====',
738
+ worker_idx=worker_idx
739
+ ),
740
+ file=sys.stderr
741
+ )
742
+ print_tb(exc_tb)
743
+ print(
744
+ _(
745
+ '{name}: {exc_val}',
746
+ name=exc_type.__name__,
747
+ exc_val=exc_val
748
+ ),
749
+ file=sys.stderr
750
+ )
751
+
752
+ else:
753
+ self.worker_status.value = WorkerStatus.finished
754
+
755
+ logger.info(_(
756
+ en_message='worker `{worker}` started.',
757
+ worker=worker_name,
758
+ ))
759
+
760
+ with SettingStatusFinished():
761
+
762
+ self.worker_status.value = WorkerStatus.initializing
763
+
764
+ self.worker_status.value = WorkerStatus.launching_fem
765
+ self.fem._setup_after_parallel(self)
766
+
767
+ if wait_other_process_setup:
768
+ self.worker_status.value = WorkerStatus.waiting
769
+ while True:
770
+ self._check_and_raise_interruption()
771
+
772
+ # 他のすべての worker_status が wait 以上になったら break
773
+ logger.debug([ws.value for ws in worker_status_list])
774
+ if all([ws.value >= WorkerStatus.waiting
775
+ for ws in worker_status_list]):
776
+
777
+ # リソースの競合等を避けるため
778
+ # break する前に index 秒待つ
779
+ if isinstance(worker_idx, str):
780
+ wait_second = 0.
781
+ else:
782
+ wait_second = int(worker_idx + 1)
783
+ sleep(wait_second)
784
+ break
785
+
786
+ sleep(1)
787
+
788
+ self.worker_status.value = WorkerStatus.running
789
+
790
+ self.run()
791
+
792
+ logger.info(_(
793
+ en_message='worker `{worker}` successfully finished!',
794
+ worker=worker_name,
795
+ ))
796
+
797
+ def _logging(self):
798
+
799
+ # noinspection PyMethodParameters
800
+ class LoggingOutput:
801
+ def __enter__(self_):
802
+ self_.count = len(self.history.get_df()) + 1
803
+ logger.info(f'▼▼▼▼▼ solve {self_.count} start ▼▼▼▼▼')
804
+
805
+ def __exit__(self_, exc_type, exc_val, exc_tb):
806
+ logger.info(f'▲▲▲▲▲ solve {self_.count} end ▲▲▲▲▲\n')
807
+
808
+ return LoggingOutput()
809
+
810
+ def _load_problem_from_fem(self):
811
+ if self.fem._load_problem_from_fem and not self._done_load_problem_from_fem:
812
+ self.fem.load_variables(self)
813
+ self.fem.load_objectives(self)
814
+ self.fem.load_constraints(self)
815
+ self._done_load_problem_from_fem = True
816
+
817
+ # noinspection PyMethodMayBeStatic
818
+ def _get_additional_data(self) -> dict:
819
+ return dict()
820
+
821
+ def _collect_additional_data(self) -> dict:
822
+ additional_data = {}
823
+ additional_data.update(self._get_additional_data())
824
+ additional_data.update(self.fem._get_additional_data())
825
+ return additional_data
826
+
827
+ def _finalize_history(self):
828
+ if not self.history._finalized:
829
+ parameters = self.variable_manager.get_variables(
830
+ filter='parameter', format='raw'
831
+ )
832
+ self.history.finalize(
833
+ parameters,
834
+ list(self.objectives.keys()),
835
+ list(self.constraints.keys()),
836
+ [self.sub_fidelity_name] + list(self.sub_fidelity_models.keys()),
837
+ additional_data=self._collect_additional_data()
838
+ )
839
+
840
+ def _setup_before_parallel(self):
841
+
842
+ if not self._done_setup_before_parallel:
843
+
844
+ # check compatibility with fem if needed
845
+ variables = self.variable_manager.get_variables()
846
+ for var_name, variable in variables.items():
847
+ if variable.pass_to_fem:
848
+ self.fem._check_param_and_raise(var_name)
849
+
850
+ # resolve evaluation order
851
+ self.variable_manager.resolve()
852
+
853
+ self._done_setup_before_parallel = True
854
+
855
+ def _setup_after_parallel(self):
856
+ pass
857
+
858
+ def _finalize(self):
859
+
860
+ # check sub fidelity models
861
+ if self.sub_fidelity_models is None:
862
+ self.sub_fidelity_models = SubFidelityModels()
863
+ for sub_fidelity_model in self.sub_fidelity_models.values():
864
+ assert sub_fidelity_model.objectives.keys() == self.objectives.keys()
865
+ assert sub_fidelity_model.constraints.keys() == self.constraints.keys()
866
+
867
+ # finalize
868
+ self._load_problem_from_fem()
869
+ self._finalize_history()
870
+
871
+ # setup if needed
872
+ self._setup_before_parallel()
873
+ self._setup_after_parallel()
874
+
875
+
876
+ class SubFidelityModel(AbstractOptimizer):
877
+ pass
878
+
879
+
880
+ class SubFidelityModels(dict[str, SubFidelityModel]):
881
+
882
+ def _update(self, name, model: SubFidelityModel, fidelity: Fidelity):
883
+ model.sub_fidelity_name = name
884
+ model.fidelity = fidelity
885
+ self.update({name: model})