pyfemtet 0.5.4__tar.gz → 0.6.0__tar.gz
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.
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/PKG-INFO +1 -1
- pyfemtet-0.6.0/pyfemtet/__init__.py +1 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/_message/locales/ja/LC_MESSAGES/messages.po +1 -1
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/__init__.py +3 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/_femopt.py +33 -14
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/_femopt_core.py +99 -63
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/interface/_femtet.py +15 -4
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/optimizer/__init__.py +5 -1
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/optimizer/_base.py +5 -13
- pyfemtet-0.5.4/pyfemtet/opt/optimizer/_optuna_botorchsampler_parameter_constraint_helper.py → pyfemtet-0.6.0/pyfemtet/opt/optimizer/_optuna/_botorch_patch/enable_nonlinear_constraint.py +9 -126
- {pyfemtet-0.5.4/pyfemtet/opt/optimizer → pyfemtet-0.6.0/pyfemtet/opt/optimizer/_optuna}/_optuna.py +89 -18
- pyfemtet-0.6.0/pyfemtet/opt/optimizer/_optuna/_pof_botorch.py +1833 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample/constrained_pipe.py +2 -2
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample/her_ex40_parametric.py +2 -2
- pyfemtet-0.6.0/pyfemtet/opt/visualization/_wrapped_components/__init__.py +0 -0
- pyfemtet-0.6.0/pyfemtet/opt/visualization/result_viewer/__init__.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyproject.toml +7 -1
- pyfemtet-0.5.4/pyfemtet/__init__.py +0 -1
- pyfemtet-0.5.4/pyfemtet/opt/samples/femprj_sample/.gitignore +0 -2
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/LICENSE +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/README.md +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/_message/1. make_pot.bat +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/_message/2. make_mo.bat +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/_message/__init__.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/_message/babel.cfg +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/_message/locales/messages.pot +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/_message/messages.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/_warning.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/core.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/dispatch_extensions/__init__.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/dispatch_extensions/_impl.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/logger/__init__.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/logger/_impl.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/_test_utils/__init__.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/_test_utils/control_femtet.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/_test_utils/hyper_sphere.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/_test_utils/record_history.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/interface/__init__.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/interface/_base.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/interface/_femtet_parametric.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/interface/_femtet_with_nx/__init__.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/interface/_femtet_with_nx/_interface.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/interface/_femtet_with_nx/update_model.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/interface/_femtet_with_sldworks.py +0 -0
- {pyfemtet-0.5.4/pyfemtet/opt/prediction → pyfemtet-0.6.0/pyfemtet/opt/optimizer/_optuna}/__init__.py +0 -0
- {pyfemtet-0.5.4/pyfemtet/opt/visualization → pyfemtet-0.6.0/pyfemtet/opt/optimizer/_optuna/_botorch_patch}/__init__.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/optimizer/_scipy.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/optimizer/_scipy_scalar.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/optimizer/parameter.py +0 -0
- {pyfemtet-0.5.4/pyfemtet/opt/visualization/_complex_components → pyfemtet-0.6.0/pyfemtet/opt/prediction}/__init__.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/prediction/_base.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/prediction/single_task_gp.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample/ParametricIF.femprj +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample/ParametricIF.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample/ParametricIF_test_result.reccsv +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample/cad_ex01_NX.femprj +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample/cad_ex01_NX.prt +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample/cad_ex01_NX.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample/cad_ex01_NX_test_result.reccsv +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample/cad_ex01_SW.SLDPRT +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample/cad_ex01_SW.femprj +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample/cad_ex01_SW.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample/cad_ex01_SW_test_result.reccsv +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample/constrained_pipe.femprj +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample/constrained_pipe_test_result.reccsv +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample/gal_ex58_parametric.femprj +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample/gal_ex58_parametric.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample/gal_ex58_parametric_test_result.reccsv +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample/gau_ex08_parametric.femprj +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample/gau_ex08_parametric.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample/gau_ex08_parametric_test_result.reccsv +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample/her_ex40_parametric.femprj +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample/her_ex40_parametric_test_result.reccsv +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample/paswat_ex1_parametric.femprj +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample/paswat_ex1_parametric.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample/paswat_ex1_parametric_parallel.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample/paswat_ex1_parametric_test_result.reccsv +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample/wat_ex14_parametric.femprj +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample/wat_ex14_parametric.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample/wat_ex14_parametric_parallel.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample/wat_ex14_parametric_test_result.reccsv +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample_jp/ParametricIF_jp.femprj +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample_jp/ParametricIF_jp.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample_jp/cad_ex01_NX_jp.femprj +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample_jp/cad_ex01_NX_jp.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample_jp/cad_ex01_SW_jp.femprj +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample_jp/cad_ex01_SW_jp.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample_jp/constrained_pipe_jp.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample_jp/gal_ex58_parametric_jp.femprj +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample_jp/gal_ex58_parametric_jp.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample_jp/gau_ex08_parametric_jp.femprj +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample_jp/gau_ex08_parametric_jp.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample_jp/her_ex40_parametric_jp.femprj +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample_jp/her_ex40_parametric_jp.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample_jp/paswat_ex1_parametric_jp.femprj +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample_jp/paswat_ex1_parametric_jp.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample_jp/paswat_ex1_parametric_parallel_jp.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample_jp/wat_ex14_parametric_jp.femprj +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample_jp/wat_ex14_parametric_jp.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/samples/femprj_sample_jp/wat_ex14_parametric_parallel_jp.py +0 -0
- {pyfemtet-0.5.4/pyfemtet/opt/visualization/_process_monitor → pyfemtet-0.6.0/pyfemtet/opt/visualization}/__init__.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/visualization/_base.py +0 -0
- {pyfemtet-0.5.4/pyfemtet/opt/visualization/_wrapped_components → pyfemtet-0.6.0/pyfemtet/opt/visualization/_complex_components}/__init__.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/visualization/_complex_components/alert_region.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/visualization/_complex_components/control_femtet.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/visualization/_complex_components/main_figure_creator.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/visualization/_complex_components/main_graph.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/visualization/_complex_components/pm_graph.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/visualization/_complex_components/pm_graph_creator.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/visualization/_create_wrapped_components.py +0 -0
- {pyfemtet-0.5.4/pyfemtet/opt/visualization/result_viewer → pyfemtet-0.6.0/pyfemtet/opt/visualization/_process_monitor}/__init__.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/visualization/_process_monitor/application.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/visualization/_process_monitor/pages.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/visualization/_wrapped_components/dbc.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/visualization/_wrapped_components/dcc.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/visualization/_wrapped_components/html.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/visualization/_wrapped_components/str_enum.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/visualization/result_viewer/.gitignore +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/visualization/result_viewer/application.py +0 -0
- {pyfemtet-0.5.4 → pyfemtet-0.6.0}/pyfemtet/opt/visualization/result_viewer/pages.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.6.0"
|
|
@@ -80,7 +80,7 @@ msgstr "モデル更新に失敗しました。"
|
|
|
80
80
|
|
|
81
81
|
#: pyfemtet/message/messages.py:60
|
|
82
82
|
msgid "It was detected that the configuration of Femtet python macro constants has not been completed. The configuration was done automatically (python -m win32com.client.makepy FemtetMacro). Please restart the program."
|
|
83
|
-
msgstr "Femtet マクロの定数の設定が未完了であることが検出され、設定コマンド(python -m
|
|
83
|
+
msgstr "Femtet マクロの定数の設定が未完了であることが検出され、設定コマンド(python -m win32com.client.makepy FemtetMacro)が自動実行されました。プログラムを再実行してください。"
|
|
84
84
|
|
|
85
85
|
#: pyfemtet/message/messages.py:61
|
|
86
86
|
msgid "Failed to connect to Femtet."
|
|
@@ -9,6 +9,8 @@ from pyfemtet.opt.optimizer import AbstractOptimizer
|
|
|
9
9
|
|
|
10
10
|
from pyfemtet.opt._femopt import FEMOpt
|
|
11
11
|
|
|
12
|
+
from pyfemtet.opt._femopt_core import History
|
|
13
|
+
|
|
12
14
|
|
|
13
15
|
__all__ = [
|
|
14
16
|
'FEMOpt',
|
|
@@ -21,4 +23,5 @@ __all__ = [
|
|
|
21
23
|
'OptunaOptimizer',
|
|
22
24
|
'ScipyScalarOptimizer',
|
|
23
25
|
'ScipyOptimizer',
|
|
26
|
+
'History',
|
|
24
27
|
]
|
|
@@ -12,7 +12,7 @@ from traceback import print_exception
|
|
|
12
12
|
# 3rd-party
|
|
13
13
|
import numpy as np
|
|
14
14
|
import pandas as pd
|
|
15
|
-
from dask.distributed import LocalCluster, Client
|
|
15
|
+
from dask.distributed import LocalCluster, Client
|
|
16
16
|
|
|
17
17
|
# pyfemtet relative
|
|
18
18
|
from pyfemtet.opt.interface import FEMInterface, FemtetInterface
|
|
@@ -32,10 +32,13 @@ from pyfemtet._message import Msg, encoding
|
|
|
32
32
|
from pyfemtet.opt.optimizer.parameter import Parameter, Expression
|
|
33
33
|
from pyfemtet._warning import experimental_feature
|
|
34
34
|
|
|
35
|
+
from dask import config as cfg
|
|
36
|
+
cfg.set({'distributed.scheduler.worker-ttl': None})
|
|
35
37
|
|
|
36
|
-
|
|
38
|
+
|
|
39
|
+
def add_worker(client, worker_name, n_workers=1):
|
|
37
40
|
import sys
|
|
38
|
-
from subprocess import Popen, DEVNULL
|
|
41
|
+
from subprocess import Popen, DEVNULL, PIPE
|
|
39
42
|
|
|
40
43
|
current_n_workers = len(client.nthreads().keys())
|
|
41
44
|
|
|
@@ -43,16 +46,16 @@ def add_worker(client, worker_name):
|
|
|
43
46
|
f'{sys.executable} -m dask worker '
|
|
44
47
|
f'{client.scheduler.address} '
|
|
45
48
|
f'--nthreads 1 '
|
|
46
|
-
f'--nworkers
|
|
47
|
-
f'--name {worker_name} '
|
|
48
|
-
|
|
49
|
+
f'--nworkers {n_workers} '
|
|
50
|
+
f'--name {worker_name} ', # A unique name for this worker like ‘worker-1’. If used with -nworkers then the process number will be appended like name-0, name-1, name-2, …
|
|
51
|
+
# --no-nanny option は --nworkers と併用できない
|
|
49
52
|
shell=True,
|
|
50
53
|
stderr=DEVNULL,
|
|
51
54
|
stdout=DEVNULL,
|
|
52
55
|
)
|
|
53
56
|
|
|
54
57
|
# worker が増えるまで待つ
|
|
55
|
-
client.wait_for_workers(n_workers=current_n_workers +
|
|
58
|
+
client.wait_for_workers(n_workers=current_n_workers + n_workers)
|
|
56
59
|
|
|
57
60
|
|
|
58
61
|
class FEMOpt:
|
|
@@ -132,6 +135,7 @@ class FEMOpt:
|
|
|
132
135
|
self.monitor_process_future = None
|
|
133
136
|
self.monitor_server_kwargs = dict()
|
|
134
137
|
self.monitor_process_worker_name = None
|
|
138
|
+
self._hv_reference = None
|
|
135
139
|
|
|
136
140
|
# multiprocess 時に pickle できないオブジェクト参照の削除
|
|
137
141
|
def __getstate__(self):
|
|
@@ -385,9 +389,9 @@ class FEMOpt:
|
|
|
385
389
|
|
|
386
390
|
Warnings:
|
|
387
391
|
|
|
388
|
-
When ```strict``` == True and using OptunaOptimizer along with
|
|
389
|
-
|
|
390
|
-
During this process, the constraint function fun will be executed at each
|
|
392
|
+
When ```strict``` == True and using OptunaOptimizer along with :class:`PoFBoTorchSampler`,
|
|
393
|
+
PyFemtet will solve an optimization subproblem to propose new variables.
|
|
394
|
+
During this process, the constraint function ```fun``` will be executed at each
|
|
391
395
|
iteration of the subproblem, which may include time-consuming operations such
|
|
392
396
|
as retrieving 3D model information via FEMInterface.
|
|
393
397
|
As a result, it may not be feasible to complete the overall optimization within
|
|
@@ -406,7 +410,7 @@ class FEMOpt:
|
|
|
406
410
|
|
|
407
411
|
Instead, please do the following.
|
|
408
412
|
|
|
409
|
-
>>> def bottom_area(_, opt): #
|
|
413
|
+
>>> def bottom_area(_, opt): # Not to access the 1st argument. # doctest: +SKIP
|
|
410
414
|
... params = opt.get_parameter() # doctest: +SKIP
|
|
411
415
|
... w, d = params['width'], params['depth'] # doctest: +SKIP
|
|
412
416
|
... return w * d # doctest: +SKIP
|
|
@@ -623,14 +627,21 @@ class FEMOpt:
|
|
|
623
627
|
|
|
624
628
|
else:
|
|
625
629
|
# ローカルクラスターを構築
|
|
626
|
-
logger.info('Launching single machine cluster
|
|
630
|
+
logger.info('Launching single machine cluster... This may take tens of seconds.')
|
|
631
|
+
|
|
632
|
+
# Fixed:
|
|
633
|
+
# Nanny の管理機能は必要ないが、Python API では worker_class を Worker にすると
|
|
634
|
+
# processes 引数が無視されて Thread worker が立てられる。
|
|
635
|
+
# これは CLI の --no-nanny オプションも同様らしい。
|
|
636
|
+
|
|
637
|
+
# クラスターの構築
|
|
627
638
|
cluster = LocalCluster(
|
|
628
639
|
processes=True,
|
|
629
|
-
n_workers=n_parallel,
|
|
640
|
+
n_workers=n_parallel,
|
|
630
641
|
threads_per_worker=1,
|
|
631
|
-
worker_class=Worker,
|
|
632
642
|
)
|
|
633
643
|
logger.info('LocalCluster launched successfully.')
|
|
644
|
+
|
|
634
645
|
self.client = Client(cluster, direct_to_workers=False)
|
|
635
646
|
self.scheduler_address = self.client.scheduler.address
|
|
636
647
|
logger.info('Client launched successfully.')
|
|
@@ -655,6 +666,7 @@ class FEMOpt:
|
|
|
655
666
|
model_name=self.fem.model_name
|
|
656
667
|
)
|
|
657
668
|
)
|
|
669
|
+
|
|
658
670
|
# Femtet の parametric 設定を目的関数に用いるかどうか
|
|
659
671
|
if self.fem.parametric_output_indexes_use_as_objective is not None:
|
|
660
672
|
from pyfemtet.opt.interface._femtet_parametric import add_parametric_results_as_objectives
|
|
@@ -665,8 +677,14 @@ class FEMOpt:
|
|
|
665
677
|
indexes,
|
|
666
678
|
directions,
|
|
667
679
|
)
|
|
680
|
+
|
|
681
|
+
# Femtet の confirm_before_exit のセット
|
|
682
|
+
self.fem.confirm_before_exit = confirm_before_exit
|
|
683
|
+
self.fem.kwargs['confirm_before_exit'] = confirm_before_exit
|
|
684
|
+
|
|
668
685
|
logger.info('Femtet loaded successfully.')
|
|
669
686
|
|
|
687
|
+
|
|
670
688
|
# actor の設定
|
|
671
689
|
self.status = OptimizationStatus(_client)
|
|
672
690
|
self.worker_status_list = [OptimizationStatus(_client, name) for name in worker_addresses] # tqdm 検討
|
|
@@ -678,6 +696,7 @@ class FEMOpt:
|
|
|
678
696
|
list(self.opt.constraints.keys()),
|
|
679
697
|
_client,
|
|
680
698
|
metadata,
|
|
699
|
+
self._hv_reference
|
|
681
700
|
)
|
|
682
701
|
logger.info('Status Actor initialized successfully.')
|
|
683
702
|
|
|
@@ -453,18 +453,12 @@ class History:
|
|
|
453
453
|
cns_names (List[str], optional): The names of constraints. Defaults to None.
|
|
454
454
|
client (dask.distributed.Client): Dask client.
|
|
455
455
|
additional_metadata (str, optional): metadata of optimization process.
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
ENCODING (str): Encoding of csv file. Default to 'cp932'.
|
|
463
|
-
prm_names (str): User defined names of parameters.
|
|
464
|
-
obj_names (str): User defined names of objectives.
|
|
465
|
-
cns_names (str): User defined names of constraints.
|
|
466
|
-
is_restart (bool): If the optimization process is a continuation of another process or not.
|
|
467
|
-
is_processing (bool): The optimization is running or not.
|
|
456
|
+
hv_reference (str or list[float or np.ndarray, optional):
|
|
457
|
+
The method to calculate hypervolume or
|
|
458
|
+
the reference point itself.
|
|
459
|
+
Valid values are 'dynamic-pareto' or
|
|
460
|
+
'dynamic-nadir' or 'nadir' or 'pareto'
|
|
461
|
+
or fixed point (in objective function space).
|
|
468
462
|
|
|
469
463
|
"""
|
|
470
464
|
|
|
@@ -487,7 +481,10 @@ class History:
|
|
|
487
481
|
cns_names=None,
|
|
488
482
|
client=None,
|
|
489
483
|
additional_metadata=None,
|
|
484
|
+
hv_reference=None,
|
|
490
485
|
):
|
|
486
|
+
# hypervolume 計算メソッド
|
|
487
|
+
self._hv_reference = hv_reference or 'dynamic-pareto'
|
|
491
488
|
|
|
492
489
|
# 引数の処理
|
|
493
490
|
self.path = history_path # .csv
|
|
@@ -739,59 +736,98 @@ class History:
|
|
|
739
736
|
|
|
740
737
|
def _calc_hypervolume(self, objectives, df):
|
|
741
738
|
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
# 計算結果を履歴の一部に割り当て
|
|
778
|
-
# idx: [False, True, False, True, True, False, ...]
|
|
779
|
-
# hvs: [ 1, 2, 3, ...]
|
|
780
|
-
# want:[ 0, 1, 1, 2, 3, 3, ...]
|
|
781
|
-
hvs_index = -1
|
|
782
|
-
for i in range(len(df)):
|
|
783
|
-
|
|
784
|
-
# process hvs index
|
|
785
|
-
if idx[i]:
|
|
786
|
-
hvs_index += 1
|
|
787
|
-
|
|
788
|
-
# get hv
|
|
789
|
-
if hvs_index < 0:
|
|
790
|
-
hypervolume = 0.
|
|
739
|
+
if len(objectives) < 2:
|
|
740
|
+
df.loc[len(df) - 1, 'hypervolume'] = 0.
|
|
741
|
+
return
|
|
742
|
+
|
|
743
|
+
# 最小化問題に変換された objective values を取得
|
|
744
|
+
raw_objective_values = df[self.obj_names].values
|
|
745
|
+
objective_values = np.empty_like(raw_objective_values)
|
|
746
|
+
for n_trial in range(len(raw_objective_values)):
|
|
747
|
+
for obj_idx, (_, objective) in enumerate(objectives.items()):
|
|
748
|
+
objective_values[n_trial, obj_idx] = objective.convert(raw_objective_values[n_trial, obj_idx])
|
|
749
|
+
|
|
750
|
+
# pareto front を取得
|
|
751
|
+
def get_pareto(objective_values_, with_partial=False):
|
|
752
|
+
ret = None
|
|
753
|
+
if with_partial:
|
|
754
|
+
ret = []
|
|
755
|
+
|
|
756
|
+
pareto_set_ = np.empty((0, len(self.obj_names)))
|
|
757
|
+
for i in range(len(objective_values_)):
|
|
758
|
+
target = objective_values_[i]
|
|
759
|
+
dominated = False
|
|
760
|
+
# TODO: Array の計算に直して高速化する
|
|
761
|
+
for j in range(len(objective_values_)):
|
|
762
|
+
compare = objective_values_[j]
|
|
763
|
+
if all(target > compare):
|
|
764
|
+
dominated = True
|
|
765
|
+
break
|
|
766
|
+
if not dominated:
|
|
767
|
+
pareto_set_ = np.concatenate([pareto_set_, [target]], axis=0)
|
|
768
|
+
|
|
769
|
+
if ret is not None:
|
|
770
|
+
ret.append(np.array(pareto_set_))
|
|
771
|
+
|
|
772
|
+
if ret is not None:
|
|
773
|
+
return pareto_set_, ret
|
|
791
774
|
else:
|
|
792
|
-
|
|
775
|
+
return pareto_set_
|
|
776
|
+
|
|
777
|
+
if self._hv_reference == 'dynamic-pareto':
|
|
778
|
+
pareto_set, pareto_set_list = get_pareto(objective_values, with_partial=True)
|
|
779
|
+
for i, partial_pareto_set in enumerate(pareto_set_list):
|
|
780
|
+
ref_point = pareto_set.max(axis=0) + 1e-8
|
|
781
|
+
hv = compute_hypervolume(partial_pareto_set, ref_point)
|
|
782
|
+
df.loc[i, 'hypervolume'] = hv
|
|
783
|
+
return
|
|
784
|
+
|
|
785
|
+
elif self._hv_reference == 'dynamic-nadir':
|
|
786
|
+
_, pareto_set_list = get_pareto(objective_values, with_partial=True)
|
|
787
|
+
for i, partial_pareto_set in enumerate(pareto_set_list):
|
|
788
|
+
ref_point = objective_values.max(axis=0) + 1e-8
|
|
789
|
+
hv = compute_hypervolume(partial_pareto_set, ref_point)
|
|
790
|
+
df.loc[i, 'hypervolume'] = hv
|
|
791
|
+
return
|
|
792
|
+
|
|
793
|
+
elif self._hv_reference == 'nadir':
|
|
794
|
+
pareto_set = get_pareto(objective_values)
|
|
795
|
+
ref_point = objective_values.max(axis=0) + 1e-8
|
|
796
|
+
hv = compute_hypervolume(pareto_set, ref_point)
|
|
797
|
+
df.loc[len(df) - 1, 'hypervolume'] = hv
|
|
798
|
+
return
|
|
799
|
+
|
|
800
|
+
elif self._hv_reference == 'pareto':
|
|
801
|
+
pareto_set = get_pareto(objective_values)
|
|
802
|
+
ref_point = pareto_set.max(axis=0) + 1e-8
|
|
803
|
+
hv = compute_hypervolume(pareto_set, ref_point)
|
|
804
|
+
df.loc[len(df) - 1, 'hypervolume'] = hv
|
|
805
|
+
return
|
|
806
|
+
|
|
807
|
+
elif (
|
|
808
|
+
isinstance(self._hv_reference, np.ndarray)
|
|
809
|
+
or isinstance(self._hv_reference, list)
|
|
810
|
+
):
|
|
811
|
+
_buff = np.array(self._hv_reference)
|
|
812
|
+
assert _buff.shape == (len(self.obj_names),)
|
|
813
|
+
|
|
814
|
+
ref_point = np.array(
|
|
815
|
+
[obj.convert(raw_value) for obj, raw_value in zip(objectives.values(), _buff)]
|
|
816
|
+
)
|
|
793
817
|
|
|
794
|
-
|
|
818
|
+
_buff = get_pareto(objective_values)
|
|
819
|
+
|
|
820
|
+
pareto_set = np.empty((0, len(objectives)))
|
|
821
|
+
for pareto_sol in _buff:
|
|
822
|
+
if all(pareto_sol < ref_point):
|
|
823
|
+
pareto_set = np.concatenate([pareto_set, [pareto_sol]], axis=0)
|
|
824
|
+
|
|
825
|
+
hv = compute_hypervolume(pareto_set, ref_point)
|
|
826
|
+
df.loc[len(df) - 1, 'hypervolume'] = hv
|
|
827
|
+
return
|
|
828
|
+
|
|
829
|
+
else:
|
|
830
|
+
raise NotImplementedError(f'Invalid Hypervolume reference point calculation method: {self._hv_reference}')
|
|
795
831
|
|
|
796
832
|
def save(self, _f=None):
|
|
797
833
|
"""Save csv file."""
|
|
@@ -78,6 +78,10 @@ class FemtetInterface(FEMInterface):
|
|
|
78
78
|
it will be None and no parametric outputs are used
|
|
79
79
|
as objectives.
|
|
80
80
|
|
|
81
|
+
confirm_before_exit (bool):
|
|
82
|
+
Whether to confirm before (abnormal) termination.
|
|
83
|
+
Default is True.
|
|
84
|
+
|
|
81
85
|
**kwargs: Additional arguments from inherited classes.
|
|
82
86
|
|
|
83
87
|
Warning:
|
|
@@ -103,6 +107,7 @@ class FemtetInterface(FEMInterface):
|
|
|
103
107
|
allow_without_project: bool = False, # main でのみ True を許容したいので super() の引数にしない。
|
|
104
108
|
open_result_with_gui: bool = True,
|
|
105
109
|
parametric_output_indexes_use_as_objective: dict[int, str or float] = None,
|
|
110
|
+
confirm_before_exit: bool = True,
|
|
106
111
|
**kwargs # 継承されたクラスからの引数
|
|
107
112
|
):
|
|
108
113
|
|
|
@@ -132,6 +137,7 @@ class FemtetInterface(FEMInterface):
|
|
|
132
137
|
self.parametric_output_indexes_use_as_objective = parametric_output_indexes_use_as_objective
|
|
133
138
|
self._original_autosave_enabled = _get_autosave_enabled()
|
|
134
139
|
_set_autosave_enabled(False)
|
|
140
|
+
self.confirm_before_exit = confirm_before_exit
|
|
135
141
|
|
|
136
142
|
# dask サブプロセスのときは femprj を更新し connect_method を new にする
|
|
137
143
|
try:
|
|
@@ -169,6 +175,7 @@ class FemtetInterface(FEMInterface):
|
|
|
169
175
|
open_result_with_gui=self.open_result_with_gui,
|
|
170
176
|
parametric_output_indexes_use_as_objective=self.parametric_output_indexes_use_as_objective,
|
|
171
177
|
save_pdt=self.save_pdt,
|
|
178
|
+
confirm_before_exit=self.confirm_before_exit,
|
|
172
179
|
**kwargs
|
|
173
180
|
)
|
|
174
181
|
|
|
@@ -241,7 +248,8 @@ class FemtetInterface(FEMInterface):
|
|
|
241
248
|
print('================')
|
|
242
249
|
print(message)
|
|
243
250
|
print('================')
|
|
244
|
-
|
|
251
|
+
if self.confirm_before_exit:
|
|
252
|
+
input('Press enter to finish...')
|
|
245
253
|
raise RuntimeError(message)
|
|
246
254
|
|
|
247
255
|
if self.Femtet is None:
|
|
@@ -532,7 +540,8 @@ class FemtetInterface(FEMInterface):
|
|
|
532
540
|
logger.error(Msg.ERR_CANNOT_ACCESS_API + 'GetVariableNames_py')
|
|
533
541
|
logger.error(Msg.CERTIFY_MACRO_VERSION)
|
|
534
542
|
print('================')
|
|
535
|
-
|
|
543
|
+
if self.confirm_before_exit:
|
|
544
|
+
input(Msg.ENTER_TO_QUIT)
|
|
536
545
|
raise e
|
|
537
546
|
|
|
538
547
|
if variable_names is not None:
|
|
@@ -543,7 +552,8 @@ class FemtetInterface(FEMInterface):
|
|
|
543
552
|
logger.error(message)
|
|
544
553
|
logger.error(f'`{param_name}` not in {variable_names}')
|
|
545
554
|
print('================')
|
|
546
|
-
|
|
555
|
+
if self.confirm_before_exit:
|
|
556
|
+
input(Msg.ENTER_TO_QUIT)
|
|
547
557
|
raise RuntimeError(message)
|
|
548
558
|
else:
|
|
549
559
|
return None
|
|
@@ -736,7 +746,8 @@ class FemtetInterface(FEMInterface):
|
|
|
736
746
|
logger.error(Msg.ERR_CANNOT_ACCESS_API + 'Femtet.Exit()')
|
|
737
747
|
logger.error(Msg.CERTIFY_MACRO_VERSION)
|
|
738
748
|
print('================')
|
|
739
|
-
|
|
749
|
+
if self.confirm_before_exit:
|
|
750
|
+
input(Msg.ENTER_TO_QUIT)
|
|
740
751
|
raise e
|
|
741
752
|
|
|
742
753
|
else:
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
from pyfemtet.opt.optimizer._base import AbstractOptimizer, logger, OptimizationMethodChecker
|
|
2
|
-
from pyfemtet.opt.optimizer._optuna import OptunaOptimizer
|
|
2
|
+
from pyfemtet.opt.optimizer._optuna._optuna import OptunaOptimizer
|
|
3
3
|
from pyfemtet.opt.optimizer._scipy import ScipyOptimizer
|
|
4
4
|
from pyfemtet.opt.optimizer._scipy_scalar import ScipyScalarOptimizer
|
|
5
5
|
|
|
6
|
+
from pyfemtet.opt.optimizer._optuna._pof_botorch import PoFBoTorchSampler, PoFConfig
|
|
7
|
+
|
|
6
8
|
__all__ = [
|
|
7
9
|
'ScipyScalarOptimizer',
|
|
8
10
|
'ScipyOptimizer',
|
|
9
11
|
'OptunaOptimizer',
|
|
10
12
|
'AbstractOptimizer',
|
|
11
13
|
'logger',
|
|
14
|
+
'PoFBoTorchSampler',
|
|
15
|
+
'PoFConfig',
|
|
12
16
|
]
|
|
@@ -142,6 +142,7 @@ class AbstractOptimizer(ABC):
|
|
|
142
142
|
self.subprocess_idx = None
|
|
143
143
|
self._exception = None
|
|
144
144
|
self.method_checker: OptimizationMethodChecker = OptimizationMethodChecker(self)
|
|
145
|
+
self._retry_counter = 0
|
|
145
146
|
|
|
146
147
|
# ===== algorithm specific methods =====
|
|
147
148
|
@abstractmethod
|
|
@@ -176,13 +177,11 @@ class AbstractOptimizer(ABC):
|
|
|
176
177
|
|
|
177
178
|
# Optimizer の x の更新
|
|
178
179
|
self.set_parameter_values(x)
|
|
179
|
-
|
|
180
|
-
logger.info('---------------------')
|
|
181
180
|
logger.info(f'input: {x}')
|
|
182
181
|
|
|
183
182
|
# FEM の更新
|
|
184
|
-
logger.debug('fem.update() start')
|
|
185
183
|
try:
|
|
184
|
+
logger.info(f'Solving FEM...')
|
|
186
185
|
df_to_fem = self.variables.get_variables(
|
|
187
186
|
format='df',
|
|
188
187
|
filter_pass_to_fem=True
|
|
@@ -193,25 +192,20 @@ class AbstractOptimizer(ABC):
|
|
|
193
192
|
logger.info(f'{type(e).__name__} : {e}')
|
|
194
193
|
logger.info(Msg.INFO_EXCEPTION_DURING_FEM_ANALYSIS)
|
|
195
194
|
logger.info(x)
|
|
196
|
-
raise e # may be just a ModelError, etc.
|
|
195
|
+
raise e # may be just a ModelError, etc. Handling them in Concrete classes.
|
|
197
196
|
|
|
198
197
|
# y, _y, c の更新
|
|
199
|
-
logger.debug('calculate y start')
|
|
200
198
|
y = [obj.calc(self.fem) for obj in self.objectives.values()]
|
|
201
199
|
|
|
202
|
-
logger.debug('calculate _y start')
|
|
203
200
|
_y = [obj.convert(value) for obj, value in zip(self.objectives.values(), y)]
|
|
204
201
|
|
|
205
|
-
logger.debug('calculate c start')
|
|
206
202
|
c = [cns.calc(self.fem) for cns in self.constraints.values()]
|
|
207
203
|
|
|
208
|
-
|
|
209
|
-
|
|
204
|
+
# register to history
|
|
210
205
|
df_to_opt = self.variables.get_variables(
|
|
211
206
|
format='df',
|
|
212
207
|
filter_parameter=True,
|
|
213
208
|
)
|
|
214
|
-
|
|
215
209
|
self.history.record(
|
|
216
210
|
df_to_opt,
|
|
217
211
|
self.objectives,
|
|
@@ -223,9 +217,7 @@ class AbstractOptimizer(ABC):
|
|
|
223
217
|
postprocess_args=self.fem._create_postprocess_args(),
|
|
224
218
|
)
|
|
225
219
|
|
|
226
|
-
logger.
|
|
227
|
-
|
|
228
|
-
logger.info(f'output: {_y}')
|
|
220
|
+
logger.info(f'output: {y}')
|
|
229
221
|
|
|
230
222
|
return np.array(y), np.array(_y), np.array(c)
|
|
231
223
|
|