pyfemtet 1.0.0b0__py3-none-any.whl → 1.0.1__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.

pyfemtet/_util/df_util.py CHANGED
@@ -1,3 +1,4 @@
1
+ from math import isnan
1
2
  import pandas as pd
2
3
 
3
4
 
@@ -9,8 +10,24 @@ __all__ = [
9
10
 
10
11
  def get_index(df, equality_filters):
11
12
  # フィルタ条件に一致する行のインデックスを取得
13
+
14
+ # na との == での比較は常に False なので別処理するために別リストを作る
15
+ want_na_keys = []
16
+ for key, value in equality_filters.items():
17
+ if isinstance(value, float):
18
+ if isnan(value):
19
+ want_na_keys.append(key)
20
+ [equality_filters.pop(key) for key in want_na_keys]
21
+
22
+ # na 以外の比較
12
23
  # noinspection PyUnresolvedReferences
13
- return (df[list(equality_filters.keys())] == pd.Series(equality_filters)).all(axis=1)
24
+ out: pd.Series = (df[list(equality_filters.keys())] == pd.Series(equality_filters)).all(axis=1)
25
+
26
+ # na との比較
27
+ for key in want_na_keys:
28
+ out = out & df[key].isna()
29
+
30
+ return out
14
31
 
15
32
 
16
33
  def get_partial_df(df: pd.DataFrame, equality_filters: dict):
pyfemtet/_util/helper.py CHANGED
@@ -1,6 +1,9 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from typing import Callable
4
+
5
+ import string
6
+ import secrets
4
7
  import warnings
5
8
  from time import time, sleep
6
9
  from threading import Thread
@@ -10,6 +13,7 @@ from pyfemtet._i18n import _
10
13
  __all__ = [
11
14
  'float_',
12
15
  'time_counting',
16
+ 'generate_random_id',
13
17
  ]
14
18
 
15
19
 
@@ -92,3 +96,8 @@ def time_counting(
92
96
  warning_message,
93
97
  warning_fun,
94
98
  )
99
+
100
+
101
+ def generate_random_id(length: int = 16) -> str:
102
+ alphabet = string.ascii_letters + string.digits
103
+ return ''.join(secrets.choice(alphabet) for _ in range(length))
pyfemtet/opt/femopt.py CHANGED
@@ -29,6 +29,19 @@ logger = get_module_logger('opt.femopt', False)
29
29
 
30
30
 
31
31
  class FEMOpt:
32
+ """
33
+ A class to manage finite element method (FEM) optimization using a specified optimizer and FEM interface.
34
+
35
+ Attributes:
36
+ opt (AbstractOptimizer): The optimizer instance to be used for optimization.
37
+ monitor_info (dict[str, str | int | None]): Dictionary to store monitoring information such as host and port.
38
+
39
+ Args:
40
+ fem (AbstractFEMInterface, optional): An instance of a FEM interface. Defaults to None, in which case a FemtetInterface is used.
41
+ opt (AbstractOptimizer, optional): An optimizer instance. Defaults to None, in which case OptunaOptimizer is used.
42
+
43
+ """
44
+
32
45
  opt: AbstractOptimizer
33
46
 
34
47
  def __init__(
@@ -18,6 +18,7 @@ import pandas as pd
18
18
  import pyfemtet
19
19
 
20
20
  from pyfemtet._i18n import *
21
+ from pyfemtet._util.helper import generate_random_id
21
22
  from pyfemtet._util.df_util import *
22
23
  from pyfemtet._util.dask_util import *
23
24
  from pyfemtet._util.str_enum import StrEnum
@@ -43,7 +44,10 @@ __all__ = [
43
44
  'MAIN_FILTER',
44
45
  ]
45
46
 
46
- MAIN_FILTER: dict = {'sub_fidelity_name': MAIN_FIDELITY_NAME}
47
+ MAIN_FILTER: dict = {
48
+ 'sub_fidelity_name': MAIN_FIDELITY_NAME,
49
+ 'sub_sampling': float('nan')
50
+ }
47
51
 
48
52
 
49
53
  logger = get_module_logger('opt.history', False)
@@ -126,9 +130,10 @@ class DataFrameWrapper:
126
130
 
127
131
  __df: pd.DataFrame
128
132
  _lock_name = 'edit-df'
129
- _dataset_name = 'df'
133
+ _dataset_name: str
130
134
 
131
135
  def __init__(self, df: pd.DataFrame):
136
+ self._dataset_name = 'df-' + generate_random_id()
132
137
  self.set_df(df)
133
138
 
134
139
  def __len__(self):
@@ -1053,6 +1058,14 @@ class Records:
1053
1058
 
1054
1059
  with self.df_wrapper.lock_if_not_locked:
1055
1060
 
1061
+ # check trial_id is filled
1062
+ trial_processed = False
1063
+ if processing_df['trial_id'].notna().all():
1064
+ id_to_n: dict = {tid: i + 1 for i, tid
1065
+ in enumerate(processing_df['trial_id'].unique())}
1066
+ processing_df['trial'] = processing_df['trial_id'].map(id_to_n)
1067
+ trial_processed = True
1068
+
1056
1069
  # update main fidelity
1057
1070
  equality_filters = MAIN_FILTER
1058
1071
  mgr = EntireDependentValuesCalculator(
@@ -1062,13 +1075,13 @@ class Records:
1062
1075
  )
1063
1076
  mgr.update_optimality()
1064
1077
  mgr.update_hypervolume()
1065
- mgr.update_trial_number()
1078
+ if not trial_processed:
1079
+ mgr.update_trial_number() # per_fidelity
1066
1080
  pdf = mgr.partial_df
1067
1081
  apply_partial_df(df=processing_df, partial_df=pdf, equality_filters=equality_filters)
1068
1082
 
1069
1083
  # update sub fidelity
1070
- entire_df = self.df_wrapper.get_df()
1071
- sub_fidelity_names: list = np.unique(entire_df['sub_fidelity_name']).tolist()
1084
+ sub_fidelity_names: list = np.unique(processing_df['sub_fidelity_name']).tolist()
1072
1085
  if MAIN_FIDELITY_NAME in sub_fidelity_names:
1073
1086
  sub_fidelity_names.remove(MAIN_FIDELITY_NAME)
1074
1087
  for sub_fidelity_name in sub_fidelity_names:
@@ -1078,7 +1091,8 @@ class Records:
1078
1091
  equality_filters,
1079
1092
  processing_df
1080
1093
  )
1081
- mgr.update_trial_number()
1094
+ if not trial_processed:
1095
+ mgr.update_trial_number() # per_fidelity
1082
1096
  pdf = mgr.partial_df
1083
1097
  apply_partial_df(df=processing_df, partial_df=pdf, equality_filters=equality_filters)
1084
1098
 
@@ -258,8 +258,6 @@ class ExcelInterface(COMInterface):
258
258
  force_override_when_load: bool = False,
259
259
  ):
260
260
 
261
- show_experimental_warning("ExcelInterface")
262
-
263
261
  def proc_path(path_):
264
262
  if path_ is None:
265
263
  return self._original_input_xlsm_path
@@ -102,8 +102,6 @@ class FemtetInterface(COMInterface):
102
102
  If you do not want to delete the swept table,
103
103
  make a copy of the original file.
104
104
 
105
- **kwargs: Additional arguments from inherited classes.
106
-
107
105
  Warning:
108
106
  Even if you specify ``strictly_pid_specify=True`` on the constructor,
109
107
  **the connection behavior is like** ``strictly_pid_specify=False`` **in parallel processing**
@@ -119,6 +117,7 @@ class FemtetInterface(COMInterface):
119
117
 
120
118
  com_members = {'Femtet': 'FemtetMacro.Femtet'}
121
119
  _show_parametric_index_warning = True # for GUI
120
+ _femtet_connection_timeout = 10
122
121
 
123
122
  def __init__(
124
123
  self,
@@ -316,9 +315,9 @@ class FemtetInterface(COMInterface):
316
315
  logger.info("└ Try to connect existing Femtet process.")
317
316
  # 既存の Femtet を探して Dispatch する。
318
317
  if pid is None:
319
- self.Femtet, self.femtet_pid = dispatch_femtet(timeout=5)
318
+ self.Femtet, self.femtet_pid = dispatch_femtet(timeout=self._femtet_connection_timeout)
320
319
  else:
321
- self.Femtet, self.femtet_pid = dispatch_specific_femtet(pid, timeout=5)
320
+ self.Femtet, self.femtet_pid = dispatch_specific_femtet(pid, timeout=self._femtet_connection_timeout)
322
321
  self.connected_method = "existing"
323
322
 
324
323
  def connect_femtet(self, connect_method: str = "auto", pid: int or None = None):
@@ -20,6 +20,26 @@ if TYPE_CHECKING:
20
20
 
21
21
 
22
22
  class FemtetWithSolidworksInterface(FemtetInterface, SolidworksInterface, AbstractFEMInterface):
23
+ """
24
+ Interface class integrating Femtet and SolidWorks operations.
25
+
26
+ This class combines the capabilities of both Femtet and SolidWorks interfaces, allowing
27
+ coordinated operation between simulation (Femtet) and CAD manipulation (SolidWorks).
28
+
29
+ Args:
30
+ sldprt_path (str): Path to the SolidWorks part file (.sldprt).
31
+ femprj_path (str, optional): Path to the Femtet project file (.femprj). Defaults to None.
32
+ model_name (str, optional): Name of the model in the project. Defaults to None.
33
+ connect_method (str, optional): Connection method for Femtet. Defaults to "auto".
34
+ save_pdt (str, optional): Specifies which data to save. Defaults to "all".
35
+ strictly_pid_specify (bool, optional): Whether to strictly specify parameter IDs. Defaults to True.
36
+ allow_without_project (bool, optional): If True, allows operation without a project file. Defaults to False.
37
+ open_result_with_gui (bool, optional): If True, open results with GUI. Defaults to True.
38
+ parametric_output_indexes_use_as_objective (dict[int, str | float], optional): Indexes for parametric output used as objectives. Defaults to None.
39
+ always_open_copy (bool, optional): If True, always open a copy of the project. Defaults to False.
40
+ close_solidworks_on_terminate (bool, optional): If True, SolidWorks will close when this object is destroyed. Defaults to False.
41
+ solidworks_visible (bool, optional): If True, SolidWorks will be started in visible mode. Defaults to True.
42
+ """
23
43
 
24
44
  def __init__(
25
45
  self,
@@ -41,6 +41,27 @@ class FileNotOpenedError(Exception):
41
41
 
42
42
  # noinspection PyPep8Naming
43
43
  class SolidworksInterface(COMInterface):
44
+ """
45
+ Interface class for interacting with SolidWorks through COM automation.
46
+
47
+ This class manages the connection and interaction with SolidWorks using its COM interface.
48
+ It handles initialization, visibility, and clean termination of the SolidWorks application.
49
+
50
+ Attributes:
51
+ swApp (CDispatch): The COM dispatch object for SolidWorks application.
52
+ com_members (dict): Mapping of COM member names to their interface strings.
53
+ sldprt_path (str): Absolute path to the SolidWorks part file (.sldprt).
54
+ quit_solidworks_on_terminate (bool): Whether to close SolidWorks upon object destruction.
55
+ solidworks_visible (bool): Whether the SolidWorks application window is visible.
56
+
57
+ Args:
58
+ sldprt_path (str): Path to the SolidWorks part file (.sldprt).
59
+ close_solidworks_on_terminate (bool, optional): If True, SolidWorks will close when this object is destroyed. Defaults to False.
60
+ visible (bool, optional): If True, SolidWorks will be started in visible mode. Defaults to True.
61
+
62
+ Raises:
63
+ AssertionError: If the specified part file does not exist.
64
+ """
44
65
 
45
66
  swApp: CDispatch
46
67
  com_members = {'swApp': 'SLDWORKS.Application'}
@@ -434,6 +434,7 @@ class AbstractOptimizer:
434
434
 
435
435
  def __init__(self, opt: AbstractOptimizer):
436
436
  self.opt: AbstractOptimizer = opt
437
+ self.subsampling_idx: SubSampling | None = None
437
438
 
438
439
  def _preprocess(self):
439
440
  pass
@@ -460,6 +461,7 @@ class AbstractOptimizer:
460
461
  variables_pass_to_fem: dict[str, SupportedVariableTypes],
461
462
  history: History = None,
462
463
  datetime_start=None,
464
+ trial_id=None,
463
465
  ) -> _FReturnValue:
464
466
 
465
467
  # create context
@@ -486,6 +488,8 @@ class AbstractOptimizer:
486
488
  {obj_name: ObjectiveResult(obj, opt_.fem, float('nan'))
487
489
  for obj_name, obj in opt_.objectives.items()}
488
490
  )
491
+ record.sub_sampling = self.subsampling_idx
492
+ record.trial_id = trial_id
489
493
  record.sub_fidelity_name = opt_.sub_fidelity_name
490
494
  record.fidelity = opt_.fidelity
491
495
  record.datetime_start = datetime_start
@@ -498,7 +502,8 @@ class AbstractOptimizer:
498
502
  raise SkipSolve
499
503
 
500
504
  # start solve
501
- if opt_.sub_fidelity_models != MAIN_FIDELITY_NAME:
505
+ if opt_.sub_fidelity_name != MAIN_FIDELITY_NAME:
506
+ logger.info('----------')
502
507
  logger.info(_('fidelity: ({name})', name=opt_.sub_fidelity_name))
503
508
  logger.info(_('input variables:'))
504
509
  logger.info(parameters)
@@ -629,7 +634,9 @@ class AbstractOptimizer:
629
634
  x: TrialInput,
630
635
  x_pass_to_fem_: dict[str, SupportedVariableTypes],
631
636
  opt_: AbstractOptimizer | None = None,
637
+ trial_id: str =None,
632
638
  ) -> _FReturnValue | None:
639
+ """Nothing will be raised even if infeasible."""
633
640
 
634
641
  vm = self.opt.variable_manager
635
642
 
@@ -643,32 +650,40 @@ class AbstractOptimizer:
643
650
  # if opt_ is not self, update variable manager
644
651
  opt_.variable_manager = vm
645
652
 
646
- # preprocess
647
- self._preprocess()
653
+ # noinspection PyMethodParameters
654
+ class Process:
655
+ def __enter__(self_):
656
+ # preprocess
657
+ self._preprocess()
648
658
 
649
- # declare output
650
- f_return = None
659
+ def __exit__(self_, exc_type, exc_val, exc_tb):
660
+ # postprocess
661
+ self._postprocess()
651
662
 
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
- )
663
+ with Process():
658
664
 
659
- except HardConstraintViolation as e:
660
- self._hard_constraint_handling(e)
665
+ # declare output
666
+ f_return = None
661
667
 
662
- except _HiddenConstraintViolation as e:
663
- self._hidden_constraint_handling(e)
668
+ # start solve
669
+ datetime_start = datetime.datetime.now()
670
+ try:
671
+ f_return = self._solve_or_raise(
672
+ opt_, x, x_pass_to_fem_, self.opt.history,
673
+ datetime_start, trial_id
674
+ )
664
675
 
665
- except SkipSolve as e:
666
- self._skip_handling(e)
676
+ except HardConstraintViolation as e:
677
+ self._hard_constraint_handling(e)
667
678
 
668
- else:
669
- self._if_succeeded(f_return)
679
+ except _HiddenConstraintViolation as e:
680
+ self._hidden_constraint_handling(e)
670
681
 
671
- self._postprocess()
682
+ except SkipSolve as e:
683
+ self._skip_handling(e)
684
+
685
+ else:
686
+ self._if_succeeded(f_return)
672
687
 
673
688
  # check interruption
674
689
  self.opt._check_and_raise_interruption()
@@ -799,8 +814,19 @@ class AbstractOptimizer:
799
814
  # noinspection PyMethodParameters
800
815
  class LoggingOutput:
801
816
  def __enter__(self_):
802
- self_.count = len(self.history.get_df()) + 1
803
- logger.info(f'▼▼▼▼▼ solve {self_.count} start ▼▼▼▼▼')
817
+ df = self.history.get_df(
818
+ equality_filters=MAIN_FILTER
819
+ )
820
+ self_.count = len(df) + 1
821
+
822
+ succeeded_count = len(df[df['state'] == TrialState.succeeded])
823
+ succeeded_text = _(
824
+ en_message='{succeeded_count} succeeded trials',
825
+ jp_message='成功した試行数: {succeeded_count}',
826
+ succeeded_count=succeeded_count,
827
+ )
828
+
829
+ logger.info(f'▼▼▼▼▼ solve {self_.count} ({succeeded_text}) start ▼▼▼▼▼')
804
830
 
805
831
  def __exit__(self_, exc_type, exc_val, exc_tb):
806
832
  logger.info(f'▲▲▲▲▲ solve {self_.count} end ▲▲▲▲▲\n')
@@ -1,73 +1,63 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from typing import TypedDict, Sequence
4
+
5
+ import optuna.trial
6
+
3
7
  from pyfemtet.opt.problem.problem import *
4
8
  from pyfemtet.opt.history import *
5
9
  from pyfemtet.opt.optimizer._base_optimizer import *
6
10
 
7
11
 
8
12
  class OptunaAttribute:
9
- """Manage optuna user attribute
13
+ """Manage optuna user attribute.
10
14
 
11
- user attributes are:
12
- sub_fidelity_name:
15
+ By `set_user_attr_to_trial`,
16
+ key (str):
17
+ {sub_fidelity_name}(_{subsampling_idx})
18
+ value (dict):
13
19
  fidelity: ...
14
- OBJECTIVE_ATTR_KEY: ...
15
- PYFEMTET_STATE_ATTR_KEY: ...
16
- CONSTRAINT_ATTR_KEY: ...
20
+ internal_y_values: ...
21
+ violation_values: ...
22
+ pf_state: ...
17
23
 
18
24
  """
19
-
20
- OBJECTIVE_KEY = 'internal_objective'
21
- CONSTRAINT_KEY = 'constraint'
22
- PYFEMTET_TRIAL_STATE_KEY = 'pyfemtet_trial_state'
23
-
24
- sub_fidelity_name: str # key
25
- fidelity: Fidelity | None
26
- v_values: tuple | None # violation
27
- y_values: tuple | None # internal objective
28
- pf_state: TrialState | None # PyFemtet state
29
-
30
- def __init__(self, opt: AbstractOptimizer):
31
- self.sub_fidelity_name = opt.sub_fidelity_name
32
- self.fidelity = None
33
- self.v_values = None
34
- self.y_values = None
35
- self.pf_state = None
36
-
37
- # noinspection PyPropertyDefinition
38
- @classmethod
39
- def main_fidelity_key(cls):
40
- return MAIN_FIDELITY_NAME
25
+ class AttributeStructure(TypedDict):
26
+ fidelity: Fidelity | None
27
+ internal_y_values: Sequence[float] | None
28
+ violation_values: Sequence[float] | None
29
+ pf_state: TrialState | None
30
+
31
+ def __init__(
32
+ self,
33
+ opt: AbstractOptimizer,
34
+ subsampling_idx: SubSampling | None = None,
35
+ ):
36
+ # key
37
+ self.sub_fidelity_name: str = opt.sub_fidelity_name
38
+ self.subsampling_idx: SubSampling | None = subsampling_idx
39
+ # value
40
+ self.fidelity: Fidelity = opt.fidelity
41
+ self.y_values: Sequence[float] | None = None
42
+ self.v_values: Sequence[float] | None = None
43
+ self.pf_state: TrialState | None = None
41
44
 
42
45
  @property
43
- def key(self):
44
- return self.sub_fidelity_name
46
+ def key(self) -> str:
47
+ key = self.sub_fidelity_name
48
+ if self.subsampling_idx is not None:
49
+ key += f'_{self.subsampling_idx}'
50
+ return key
45
51
 
46
52
  @property
47
- def value(self):
48
- d = {}
49
- if self.fidelity:
50
- d.update({'fidelity': self.fidelity})
51
- if self.y_values:
52
- d.update({self.OBJECTIVE_KEY: self.y_values})
53
- if self.v_values:
54
- d.update({self.CONSTRAINT_KEY: self.v_values})
55
- if self.pf_state:
56
- d.update({self.PYFEMTET_TRIAL_STATE_KEY: self.pf_state})
57
- return d
58
-
59
- @staticmethod
60
- def get_fidelity(optuna_attribute: OptunaAttribute):
61
- return optuna_attribute.value['fidelity']
62
-
63
- @staticmethod
64
- def get_violation(optuna_attribute: OptunaAttribute):
65
- return optuna_attribute.value[OptunaAttribute.CONSTRAINT_KEY]
66
-
67
- @staticmethod
68
- def get_violation_from_trial_attr(trial_attr: dict): # value is OptunaAttribute.value
69
- return trial_attr[OptunaAttribute.CONSTRAINT_KEY]
70
-
71
- @staticmethod
72
- def get_pf_state_from_trial_attr(trial_attr: dict): # value is OptunaAttribute.value
73
- return trial_attr[OptunaAttribute.PYFEMTET_TRIAL_STATE_KEY]
53
+ def value(self) -> AttributeStructure:
54
+ out = self.AttributeStructure(
55
+ fidelity=self.fidelity,
56
+ internal_y_values=self.y_values,
57
+ violation_values=self.v_values,
58
+ pf_state=self.pf_state,
59
+ )
60
+ return out
61
+
62
+ def set_user_attr_to_trial(self, trial: optuna.trial.Trial):
63
+ trial.set_user_attr(self.key, self.value)
@@ -39,6 +39,37 @@ warnings.filterwarnings('ignore', 'Argument ``constraints_func`` is an experimen
39
39
 
40
40
 
41
41
  class OptunaOptimizer(AbstractOptimizer):
42
+ """
43
+ An optimizer class utilizing Optuna for hyperparameter optimization.
44
+
45
+ This class provides an interface to conduct optimization studies using Optuna.
46
+ It manages the study lifecycle, sampler configuration, and trial execution.
47
+
48
+ Attributes:
49
+ study_name (str): Name of the Optuna study.
50
+ storage (str | optuna.storages.BaseStorage): Storage URL or object for the Optuna study.
51
+ storage_path (str): Path to the Optuna study storage.
52
+ current_trial (optuna.trial.Trial | None): The current Optuna trial being evaluated.
53
+ sampler_class (type[optuna.samplers.BaseSampler]): The class of the Optuna sampler to use.
54
+ sampler_kwargs (dict): Keyword arguments to initialize the sampler.
55
+ n_trials (int | None): Number of trials to run in the study.
56
+ timeout (float | None): Maximum time allowed for the optimization.
57
+ callbacks (list): List of callback functions to invoke during optimization.
58
+
59
+ Args:
60
+ sampler_class (type[optuna.samplers.BaseSampler], optional): The sampler class for suggesting parameter values. Defaults to TPESampler if None.
61
+ sampler_kwargs (dict[str, ...], optional): Dictionary of keyword arguments for the sampler. Defaults to an empty dictionary.
62
+
63
+ Raises:
64
+ None
65
+
66
+ Examples:
67
+ >>> optimizer = OptunaOptimizer()
68
+ >>> optimizer.n_trials = 100
69
+ >>> optimizer.timeout = 600
70
+ >>> # Further configuration and usage...
71
+ """
72
+
42
73
  # system
43
74
  study_name = 'pyfemtet-study'
44
75
  storage: str | optuna.storages.BaseStorage
@@ -122,7 +153,7 @@ class OptunaOptimizer(AbstractOptimizer):
122
153
 
123
154
  y, dict_y_internal, c, record = f_return
124
155
 
125
- # convert constraint to **sorted** violation
156
+ # convert constraint to **sorted 1-d array** violation
126
157
  assert len(c) == len(self.opt_.constraints)
127
158
  v = {}
128
159
  for cns_name, cns in self.opt_.constraints.items():
@@ -139,10 +170,7 @@ class OptunaOptimizer(AbstractOptimizer):
139
170
 
140
171
  def _postprocess(self):
141
172
  # update trial attribute
142
- self.opt.current_trial.set_user_attr(
143
- self.optuna_attr.key,
144
- self.optuna_attr.value,
145
- )
173
+ self.optuna_attr.set_user_attr_to_trial(self.opt.current_trial)
146
174
 
147
175
  def _create_infeasible_constraints(self, opt_: AbstractOptimizer = None) -> tuple:
148
176
  opt_ = opt_ if opt_ is not None else self
@@ -155,9 +183,9 @@ class OptunaOptimizer(AbstractOptimizer):
155
183
  return tuple(1e9 * np.ones(count, dtype=np.float64))
156
184
 
157
185
  def _constraint(self, trial: optuna.trial.FrozenTrial):
158
- key = OptunaAttribute(self).key
159
- value = trial.user_attrs[key]
160
- return OptunaAttribute.get_violation_from_trial_attr(value)
186
+ main_key = OptunaAttribute(self).key
187
+ user_attribute: OptunaAttribute.AttributeStructure = trial.user_attrs[main_key]
188
+ return user_attribute['violation_values']
161
189
 
162
190
  def _objective(self, trial: optuna.trial.Trial):
163
191
 
@@ -226,9 +254,9 @@ class OptunaOptimizer(AbstractOptimizer):
226
254
 
227
255
  # To avoid trial FAILED with hard constraint
228
256
  # violation, check pf_state and raise TrialPruned.
229
- key = OptunaAttribute(self).key
230
- value = trial.user_attrs[key]
231
- state = OptunaAttribute.get_pf_state_from_trial_attr(value)
257
+ main_key = OptunaAttribute(self).key
258
+ user_attribute: OptunaAttribute.AttributeStructure = trial.user_attrs[main_key]
259
+ state: TrialState = user_attribute['pf_state']
232
260
  if state in [
233
261
  TrialState.hard_constraint_violation,
234
262
  TrialState.model_error,
@@ -245,9 +273,6 @@ class OptunaOptimizer(AbstractOptimizer):
245
273
 
246
274
  return y_internal
247
275
 
248
- if get_client() is None:
249
- self.history.save()
250
-
251
276
  def _get_callback(self, n_trials: int):
252
277
 
253
278
  # restart である場合、追加 N 回と見做す
@@ -587,16 +612,16 @@ def debug_1():
587
612
  _opt.add_parameter('x1', 1, -1, 1, step=0.1)
588
613
  _opt.add_parameter('x2', 1, -1, 1, step=0.1)
589
614
  _opt.add_categorical_parameter('x3', 'a', choices=['a', 'b', 'c'])
590
- _opt.add_constraint('cns', _cns, lower_bound=-0.9, args=(_fem, _opt))
591
- _opt.add_objective('obj1', _parabola, args=(_fem, _opt))
592
- # _opt.add_objective('obj2', _parabola2, args=(_fem, _opt))
615
+ # _opt.add_constraint('cns', _cns, lower_bound=-0.9, args=(_opt,))
616
+ _opt.add_objective('obj1', _parabola, args=(_opt,))
617
+ # _opt.add_objective('obj2', _parabola2, args=(_opt,))
593
618
 
594
619
  # # ===== sub-fidelity =====
595
620
  # __fem = NoFEM()
596
621
  # __opt = SubFidelityModel()
597
622
  # __opt.fem = __fem
598
- # __opt.add_objective('obj1', _parabola, args=(__fem, __opt))
599
- # __opt.add_objective('obj2', _parabola2, args=(__fem, __opt))
623
+ # __opt.add_objective('obj1', _parabola, args=(__opt,))
624
+ # # __opt.add_objective('obj2', _parabola2, args=(__opt,))
600
625
  #
601
626
  # _opt.add_sub_fidelity_model(name='low-fidelity', sub_fidelity_model=__opt, fidelity=0.5)
602
627
  #
@@ -622,6 +647,96 @@ def debug_1():
622
647
  _opt.history.save()
623
648
 
624
649
 
650
+ def debug_1s():
651
+ # from pyfemtet.opt.optimizer.optuna_optimizer.pof_botorch.pof_botorch_sampler import
652
+ # sampler = PoFBoTorchSampler(
653
+ # n_startup_trials=5,
654
+ # seed=42,
655
+ # constraints_func=self._constraint,
656
+ # pof_config=PoFConfig(
657
+ # # consider_pof=False,
658
+ # # feasibility_cdf_threshold='mean',
659
+ # ),
660
+ # partial_optimize_acqf_kwargs=PartialOptimizeACQFConfig(
661
+ # # gen_candidates='scipy',
662
+ # timeout_sec=5.,
663
+ # # method='SLSQP' # 'COBYLA, COBYQA, SLSQP or trust-constr
664
+ # tol=0.1,
665
+ # # scipy_minimize_kwargs=dict(),
666
+ # ),
667
+ # )
668
+ # from optuna_integration import BoTorchSampler
669
+ # sampler = BoTorchSampler(n_startup_trials=5)
670
+
671
+ os.chdir(os.path.dirname(__file__))
672
+
673
+ def _parabola(_fem: AbstractFEMInterface, _opt: AbstractOptimizer) -> float:
674
+ d = _opt.get_variables()
675
+ x1 = d['x1']
676
+ x2 = d['x2']
677
+ # if _cns(_fem, _opt) < 0:
678
+ # raise PostProcessError
679
+ return x1 ** 2 + x2 ** 2
680
+
681
+ def _parabola2(_fem: AbstractFEMInterface, _opt: AbstractOptimizer) -> float:
682
+ x = _opt.get_variables('values')
683
+ return ((x - 0.1) ** 2).sum()
684
+
685
+ def _cns(_fem: AbstractFEMInterface, _opt: AbstractOptimizer) -> float:
686
+ x = _opt.get_variables('values')
687
+ return x[0]
688
+
689
+ _fem = NoFEM()
690
+ _opt = OptunaOptimizer()
691
+ _opt.fem = _fem
692
+
693
+ # _opt.sampler = optuna.samplers.RandomSampler(seed=42)
694
+ _opt.seed = 42
695
+ _opt.sampler_class = optuna.samplers.TPESampler
696
+ # _opt.sampler_class = optuna.samplers.RandomSampler
697
+ _opt.sampler_kwargs = dict(
698
+ n_startup_trials=5,
699
+ )
700
+ _opt.n_trials = 10
701
+
702
+ _opt.add_parameter('x1', 1, -1, 1, step=0.1)
703
+ _opt.add_parameter('x2', 1, -1, 1, step=0.1)
704
+ _opt.add_categorical_parameter('x3', 'a', choices=['a', 'b', 'c'])
705
+ # _opt.add_constraint('cns', _cns, lower_bound=-0.9, args=(_opt,))
706
+ _opt.add_objective('obj1', _parabola, args=(_opt,))
707
+ # _opt.add_objective('obj2', _parabola2, args=(_opt,))
708
+
709
+ # ===== sub-fidelity =====
710
+ __fem = NoFEM()
711
+ __opt = SubFidelityModel()
712
+ __opt.fem = __fem
713
+ __opt.add_objective('obj1', _parabola, args=(__opt,))
714
+ # __opt.add_objective('obj2', _parabola2, args=(__opt,))
715
+
716
+ _opt.add_sub_fidelity_model(name='low-fidelity', sub_fidelity_model=__opt, fidelity=0.5)
717
+
718
+ def _solve_condition(_history: History):
719
+
720
+ sub_fidelity_df = _history.get_df(
721
+ {'sub_fidelity_name': 'low-fidelity'}
722
+ )
723
+ idx = sub_fidelity_df['state'] == TrialState.succeeded
724
+ pdf = sub_fidelity_df[idx]
725
+
726
+ return len(pdf) % 5 == 0
727
+
728
+ _opt.set_solve_condition(_solve_condition)
729
+
730
+ # _opt.history.path = 'restart-test.csv'
731
+ _opt.run()
732
+
733
+ # import plotly.express as px
734
+ # _df = _opt.history.get_df()
735
+ # px.scatter_3d(_df, x='x1', y='x2', z='obj', color='fidelity', opacity=0.5).show()
736
+
737
+ _opt.history.save()
738
+
739
+
625
740
  def substrate_size(Femtet):
626
741
  """基板のXY平面上での専有面積を計算します。"""
627
742
  substrate_w = Femtet.GetVariableValue('substrate_w')
@@ -669,10 +784,13 @@ def debug_3():
669
784
  opt.add_parameter(name="substrate_d", initial_value=60, lower_bound=34, upper_bound=60)
670
785
 
671
786
  opt.n_trials = 5
672
- opt.history.path = os.path.join(os.path.dirname(__file__), 'femtet-test.csv')
787
+ opt.history.path = os.path.join(os.path.dirname(__file__), 'femtet-test-2.csv')
673
788
 
674
789
  opt.run()
675
790
 
676
791
 
677
792
  if __name__ == '__main__':
793
+ debug_1()
794
+ debug_1s()
795
+ debug_2()
678
796
  debug_3()
@@ -973,9 +973,9 @@ class PoFBoTorchSampler(BoTorchSampler):
973
973
  feasible_trials: list[FrozenTrial] = []
974
974
  infeasible_trials: list[FrozenTrial] = []
975
975
  for trial in (completed_trials + pruned_trials):
976
- state: PFTrialState = OptunaAttribute.get_pf_state_from_trial_attr(
977
- trial.user_attrs[OptunaAttribute.main_fidelity_key()]
978
- )
976
+ main_key = OptunaAttribute(self.pyfemtet_optimizer).key
977
+ user_attribute: OptunaAttribute.AttributeStructure = trial.user_attrs[main_key]
978
+ state: PFTrialState = user_attribute['pf_state']
979
979
 
980
980
  if state in self.pof_config._states_to_consider_pof:
981
981
  infeasible_trials.append(trial)
@@ -36,6 +36,25 @@ class _ScipyCallback:
36
36
 
37
37
 
38
38
  class ScipyOptimizer(AbstractOptimizer):
39
+ """
40
+ Optimizer class that utilizes SciPy optimization methods.
41
+
42
+ This class serves as a wrapper around SciPy's optimization routines,
43
+ allowing customization of the optimization method, tolerance, and options.
44
+ It also provides mechanisms for handling constraints with enhancement and scaling.
45
+
46
+ Attributes:
47
+ method (str): The optimization method to use (e.g., 'BFGS', 'Nelder-Mead').
48
+ tol (float or None): Tolerance for termination.
49
+ options (dict): Additional options to pass to the SciPy optimizer.
50
+ constraint_enhancement (float): Small value added to enhance constraint handling.
51
+ constraint_scaling (float): Scaling factor applied to constraints.
52
+
53
+ Args:
54
+ method (str): The optimization method to use (e.g., 'BFGS', 'Nelder-Mead').
55
+ tol (float or None): Tolerance for termination.
56
+
57
+ """
39
58
 
40
59
  _timeout: None = None
41
60
  _n_trials: None = None
@@ -149,41 +149,59 @@ class VariableManager:
149
149
  # fun を持つ場合
150
150
  if isinstance(var, ExpressionFromFunction):
151
151
 
152
- # pop するので list をコピーしておく
153
- user_def_args = list(var.args)
152
+ # 関数に渡す引数の初期化
153
+ final_args = []
154
+ final_kwargs = {}
154
155
 
155
- # 位置引数を揃え、残りをキーワード引数にする
156
- pos_args = []
157
- kw_args = var.kwargs or {}
156
+ # 関数のシグネチャを取得
157
+ params = inspect.signature(var.fun).parameters
158
158
 
159
- # 引数順に調べる
160
- required_arg_names = inspect.signature(var.fun).parameters.values()
161
- for p in required_arg_names:
159
+ # 用意された引数をコピー
160
+ user_args = list(var.args)
161
+ user_kwargs = var.kwargs.copy()
162
162
 
163
- # 位置引数であ(りう)る
163
+ # 関数に定義されている順に組み立て
164
+ for p in params.values():
165
+
166
+ # def sample(a, /, b, *c, d=None, **e):
167
+ # ...
168
+ # a: POSITIONAL_OR_KEYWORD
169
+ # b: POSITIONAL_OR_KEYWORD
170
+ # c: VAR_POSITIONAL
171
+ # d: KEYWORD_ONLY
172
+ # e: VAR_KEYWORD
173
+
174
+ # 位置引数で定義されているもの
164
175
  if p.kind <= inspect.Parameter.POSITIONAL_OR_KEYWORD:
165
176
 
166
177
  # 変数である
167
178
  if p.name in self.variables:
168
179
  # order 順に見ているのですでに value が正しいはず
169
- pos_args.append(self.variables[p.name].value)
180
+ final_args.append(self.variables[p.name].value)
170
181
 
171
- # ユーザー定義位置引数である
182
+ # ユーザーが供給する変数である
172
183
  else:
173
- try:
174
- pos_args.append(user_def_args.pop(0))
175
- except IndexError as e: # pop from empty list
184
+ # user kwargs にあるかまず確認する
185
+ if p.name in user_kwargs:
186
+ # 該当物を抜き出して args に追加
187
+ final_args.append(user_kwargs.pop(p.name))
188
+
189
+ # user args がまだある
190
+ elif len(user_args) > 0:
191
+ # 先頭を抜き出して args に追加
192
+ final_args.append(user_args.pop(0))
193
+
194
+ # pos args が空であり、kwargs の中にもない
195
+ else:
176
196
  msg = []
177
- for p_ in required_arg_names:
197
+ for p_ in params.values():
178
198
  if p_.kind == inspect.Parameter.VAR_POSITIONAL:
179
199
  msg.append(f'*{p_.name}')
180
200
  elif p_.kind == inspect.Parameter.VAR_KEYWORD:
181
201
  msg.append(f'**{p_.name}')
182
202
  else:
183
203
  msg.append(p_.name)
184
- raise type(e)(
185
- *e.args,
186
- _(
204
+ raise RuntimeError(_(
187
205
  'Missing arguments! '
188
206
  'The arguments specified by `args`: {var_args} / '
189
207
  'The arguments specified by `kwargs`: {var_kwargs} / '
@@ -191,8 +209,7 @@ class VariableManager:
191
209
  var_args=var.args,
192
210
  var_kwargs=var.kwargs,
193
211
  msg=msg
194
- ),
195
- ) from None
212
+ ))
196
213
 
197
214
  # *args である
198
215
  elif p.kind == inspect.Parameter.VAR_POSITIONAL:
@@ -200,25 +217,64 @@ class VariableManager:
200
217
  # ユーザー定義位置引数でないとおかしい
201
218
  assert p.name not in self.variables, _('Extra positional argument name cannot be duplicated with a variable name.')
202
219
 
203
- # *args なので残り全部を pos_args に入れる
204
- pos_args.extend(user_def_args)
220
+ # *args なので残り全部を抜いて pos_args に入れる
221
+ final_args.extend(user_args)
222
+ user_args = []
205
223
 
206
- # キーワード引数である
224
+ # キーワード引数で定義されているもの
207
225
  elif p.kind == inspect.Parameter.KEYWORD_ONLY:
208
226
 
209
227
  # 変数である
210
228
  if p.name in self.variables:
211
229
  # order 順に見ているのですでに value が正しいはず
212
- kw_args.update({p.name: self.variables[p.name].value})
230
+ final_kwargs.update({p.name: self.variables[p.name].value})
213
231
 
214
- # **kwargs である
215
- else:
232
+ # ユーザーが供給する変数である
233
+ else:
234
+ # user kwargs にあるかまず確認する
235
+ if p.name in user_kwargs:
236
+ # 該当物を抜き出して kwargs に追加
237
+ final_kwargs.update({p.name: user_kwargs.pop(p.name)})
238
+
239
+ # user args がまだある
240
+ elif len(user_args) > 0:
241
+ # 先頭を抜き出して args に追加
242
+ final_kwargs.update({p.name: user_args.pop(0)})
243
+
244
+ # pos args が空であり、kwargs の中にもない
245
+ else:
246
+ msg = []
247
+ for p_ in params.values():
248
+ if p_.kind == inspect.Parameter.VAR_POSITIONAL:
249
+ msg.append(f'*{p_.name}')
250
+ elif p_.kind == inspect.Parameter.VAR_KEYWORD:
251
+ msg.append(f'**{p_.name}')
252
+ else:
253
+ msg.append(p_.name)
254
+ raise RuntimeError(_(
255
+ 'Missing arguments! '
256
+ 'The arguments specified by `args`: {var_args} / '
257
+ 'The arguments specified by `kwargs`: {var_kwargs} / '
258
+ 'Required arguments: {msg}',
259
+ var_args=var.args,
260
+ var_kwargs=var.kwargs,
261
+ msg=msg
262
+ ))
216
263
 
217
- # kw_args にユーザー定義キーワード引数を入れているので何もしなくてよい
264
+ # **kwargs である
265
+ elif p.kind == inspect.Parameter.VAR_KEYWORD:
266
+ # 変数であってはいけない
218
267
  assert p.name not in self.variables, _('Extra keyword argument name cannot be duplicated with a variable name.')
219
268
 
269
+ # 残りの kwargs を移す
270
+ final_kwargs.update(user_kwargs)
271
+ user_kwargs = {}
272
+
273
+ else:
274
+ raise NotImplementedError(f'Unknown argument type: {p.kind=}')
275
+
220
276
  # fun を実行する
221
- var.value = var.fun(*pos_args, **kw_args)
277
+ var.value = var.fun(*final_args, **final_kwargs)
222
278
 
223
279
  # string expression の場合
224
280
  elif isinstance(var, ExpressionFromString):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: pyfemtet
3
- Version: 1.0.0b0
3
+ Version: 1.0.1
4
4
  Summary: Design parameter optimization using Femtet.
5
5
  License: MIT
6
6
  Author: kazuma.naito
@@ -11,14 +11,14 @@ pyfemtet/_i18n/messages.py,sha256=mzTARnpZPZ-Pmcq8RdOyy5a4XGCCSxwxuoHjN_HJ0TM,17
11
11
  pyfemtet/_util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
12
  pyfemtet/_util/closing.py,sha256=JPcgHDbW249YF20bMOX6UX-LquWoCWA14KhX-qFouR4,502
13
13
  pyfemtet/_util/dask_util.py,sha256=Wm_1p_LR1yhhZNaGgazf-yQ-eialLfmqtgBjxha6qWk,2159
14
- pyfemtet/_util/df_util.py,sha256=J4eij4B99UQI2GBAu2SsIeKzwPRAnnJPJyRmjjrSMYo,860
14
+ pyfemtet/_util/df_util.py,sha256=hEae7YYhMnNmz8La2mmfAGlESqElxTdSSb-LVL2PUN4,1358
15
15
  pyfemtet/_util/excel_macro_util.py,sha256=pUCpENpM1q6AbC7wH7rMXwnQ7nIFnabQ4xlbsli9VzM,8028
16
16
  pyfemtet/_util/excel_parse_util.py,sha256=k8Y5EI9r0txwkieKUzlZqQ93b-9SMXldNIfq5ksWg28,5525
17
17
  pyfemtet/_util/femtet_access_inspection.py,sha256=91E-7wzQTZum1UIsccW26717GnTM2jxf3HeOOR7-lv0,3999
18
18
  pyfemtet/_util/femtet_autosave.py,sha256=-9DaYNsSK1QBnTOPo7EdLnMwqwAetCx_Ho5kOFMgwlk,2145
19
19
  pyfemtet/_util/femtet_exit.py,sha256=sg3GJ2gqS_V7moOJQUr4T2AphOOat_kUnGF-0AHVB68,4256
20
20
  pyfemtet/_util/femtet_version.py,sha256=9bWRMC_Exb-3rh5bg9eKfwBcgkxz_vg_eX99RPukcgA,580
21
- pyfemtet/_util/helper.py,sha256=WBsKHxXeYa9CN4EZHhlihPO8m-JFlVap2X8bDe5WGbE,2316
21
+ pyfemtet/_util/helper.py,sha256=chlfSDQ764kn0mVgBXj8WXKBrje25AX6Riia8W5zkJo,2543
22
22
  pyfemtet/_util/process_util.py,sha256=_hiRTZVZll8tnlBfXvz6GcBue4aE__jA0KnsVXe6m2A,3038
23
23
  pyfemtet/_util/sample.xlsx,sha256=OU8mBY48YESJFQrdt4OkntlE1z-6WiyUyOV-PMr09DQ,9423
24
24
  pyfemtet/_util/str_enum.py,sha256=b-mQRUsSZvk4zupYTxxSaOm3rtxfNyOajywZ82x9rmk,1441
@@ -29,28 +29,28 @@ pyfemtet/logger/__init__.py,sha256=lofBrZHr0P1hsxPUiPG1SQqKxCuSBk8zGnR7vUfCHYw,5
29
29
  pyfemtet/logger/_impl.py,sha256=uJ9el3kR-A4W2DvO_G5A6k9z2u1lkyl7GSvZ68uPy-U,6321
30
30
  pyfemtet/opt/__init__.py,sha256=1LcwTddtoi8plemxkzmX0YEKiNpAZvKn9OoNQysyDLE,339
31
31
  pyfemtet/opt/exceptions.py,sha256=M_O7jm20Y4e_QxsKF6tnEl-OrAtErUOj6hNT7eEXCO4,1327
32
- pyfemtet/opt/femopt.py,sha256=CeejR3bDipPqCJnSx2X3Af2d4oJZlLKcHIXO2TZT9fc,22567
32
+ pyfemtet/opt/femopt.py,sha256=Ufp9qJuJIEtP_lJtR-FeCkGtH_Us8imlJ1c-FVrVyLU,23186
33
33
  pyfemtet/opt/history/__init__.py,sha256=pUp3SO4R7RGzmpNDLBg_pQH0X2yzBd-oqsHXWmB33os,201
34
- pyfemtet/opt/history/_history.py,sha256=AVnWBVJDCBd4EWqG1LNb87OA9a8s2oiixGWv1ZbrUB8,48690
34
+ pyfemtet/opt/history/_history.py,sha256=NwZvZTsWmZhvOZgC-ZqRtHPRaW6OFbXYTXUuDNjmOdQ,49299
35
35
  pyfemtet/opt/history/_hypervolume.py,sha256=_IvGH71ZNreWvDQCG815Q2hS1OEvPFPQhUnNXf1UxRQ,4449
36
36
  pyfemtet/opt/history/_optimality.py,sha256=6vLySZmrrklr04Qir0hGethTykf8NYFod88NDGrBrG0,2407
37
37
  pyfemtet/opt/interface/__init__.py,sha256=D88d0yj-pQNvDij4HI2BG3OPXP5tvc5ZOomd_Jp4UE0,964
38
38
  pyfemtet/opt/interface/_base_interface.py,sha256=A1J2junrjsFXUFulYLNhLEdTZgkZS8ev0trYRXtsSWc,6540
39
39
  pyfemtet/opt/interface/_excel_interface/__init__.py,sha256=bFOmY18-j4RJc_dHQMe62GsxFwQSj7RWdvi6jxWuqyg,74
40
40
  pyfemtet/opt/interface/_excel_interface/debug-excel-interface.xlsm,sha256=TM1CEOC5XtU7qYKNnHScO02kdtXT-gc5y29m2hatsm0,114259
41
- pyfemtet/opt/interface/_excel_interface/excel_interface.py,sha256=zDl-lhveB0OSFe_9rz9fBEj1kziLyKqekPOcyTnzFm0,39735
41
+ pyfemtet/opt/interface/_excel_interface/excel_interface.py,sha256=ihYbw_i3Bcz690AwSxVAPbRK08TVYJwyF66nFs7hMd0,39682
42
42
  pyfemtet/opt/interface/_femtet_interface/__init__.py,sha256=snQruC8Rl_5rFeVmiqw9lmzdJ5mL42HpIlHIn5ytd8s,77
43
43
  pyfemtet/opt/interface/_femtet_interface/_femtet_parametric.py,sha256=dEe6udq2CBpXAcKCye90sXC0UVKok14LORitobc8DK8,10282
44
- pyfemtet/opt/interface/_femtet_interface/femtet_interface.py,sha256=VY6oRCZ4_LWBhCOvumNwSUPMuA94_f1oqpIUbI4zAmo,44710
44
+ pyfemtet/opt/interface/_femtet_interface/femtet_interface.py,sha256=6EZ-7tCTfqj5NHi9G0HbOnmpPq9eYIVlAUrHtO_IiH4,44742
45
45
  pyfemtet/opt/interface/_femtet_with_nx_interface/__init__.py,sha256=ppeoWVSmVsTmDNKpuFRVTnhjcoefQVEog3-FRiKpEe4,104
46
46
  pyfemtet/opt/interface/_femtet_with_nx_interface/femtet_with_nx_interface.py,sha256=x1drM80W7gbsZMXWh1B2rFotyEPkDbbCQkxVnl12FcI,8359
47
47
  pyfemtet/opt/interface/_femtet_with_nx_interface/model1.prt,sha256=cYVw2izr4_9PCPHOpi46XmDVOuNZ5ksuwKqzBtCZfNA,104833
48
48
  pyfemtet/opt/interface/_femtet_with_nx_interface/model1.x_t,sha256=BHZJwc9gCCfleIkPMx7hZmNLZ3y6sJamFv6OSsHWhW0,6804
49
49
  pyfemtet/opt/interface/_femtet_with_nx_interface/update_model.py,sha256=2U5SJWnG7Tyu6PP_7mtf6dOguNuub8c_1DBRtF0XuT0,3036
50
50
  pyfemtet/opt/interface/_femtet_with_solidworks/__init__.py,sha256=5McSpy2uTmJNBylCrKt4xMSq90hlSpqyXYsjwZT3yGA,128
51
- pyfemtet/opt/interface/_femtet_with_solidworks/femtet_with_solidworks_interface.py,sha256=Wiaho2qwbnAzrpq2t7CPL2ameiexuqhWxvpWMziPsj4,4347
51
+ pyfemtet/opt/interface/_femtet_with_solidworks/femtet_with_solidworks_interface.py,sha256=TVFC9B6qJH61ipV2m8h8xFQWxYNpmqoLsLyosrqgePM,5888
52
52
  pyfemtet/opt/interface/_solidworks_interface/__init__.py,sha256=2c52Hfme1xdJepewRGVkPT4yhrZMQgzlCuqvHzEZPVk,95
53
- pyfemtet/opt/interface/_solidworks_interface/solidworks_interface.py,sha256=qeGsWhw94PfnK_HAKR08mM8mqdJfMlWAWXVE_GLLxSM,7191
53
+ pyfemtet/opt/interface/_solidworks_interface/solidworks_interface.py,sha256=f-DbgD_WymMjJl4tE6XrdRfmZ3RiuTcqrgb8EqhEZ94,8326
54
54
  pyfemtet/opt/interface/_surrogate_model_interface/__init__.py,sha256=9sjzQjJsMLdpBSpURyl8x4VQHEO_PGYgAshCHoycAPI,252
55
55
  pyfemtet/opt/interface/_surrogate_model_interface/base_surrogate_interface.py,sha256=vdYw8m09e6OCSYPsXUCXqoJcA_lpAOAYuEGmqDNgffM,6276
56
56
  pyfemtet/opt/interface/_surrogate_model_interface/botorch_interface.py,sha256=bteAg6nPAIY8M9BoVycYRDtON7p0RLGT_RuPj0JNRtM,10279
@@ -63,17 +63,17 @@ pyfemtet/opt/meta_script/__main__.py,sha256=9-QM6eZOLpZ_CxERpRu3RAMqpudorSJdPCiK
63
63
  pyfemtet/opt/meta_script/sample/sample.bas,sha256=2iuSYMgPDyAdiSDVGxRu3avjcZYnULz0l8e25YBa7SQ,27966
64
64
  pyfemtet/opt/meta_script/sample/sample.femprj,sha256=6_0ywhgXxZjdzZzQFog8mgMUEjKNCFVNlEgAWoptovk,292885
65
65
  pyfemtet/opt/optimizer/__init__.py,sha256=A4QYeF0KHEFdwoxLfkDND7ikDQ186Ryy3oXEGdakFSg,463
66
- pyfemtet/opt/optimizer/_base_optimizer.py,sha256=Pt4-fdCffcAYrv4AJ1EpJIdV-vPYJxYirlM-l74AOFQ,30549
66
+ pyfemtet/opt/optimizer/_base_optimizer.py,sha256=zOoh0o0Um2zponfxWxeHx5MV46JrkC9eYC1JmVXbbVE,31685
67
67
  pyfemtet/opt/optimizer/optuna_optimizer/__init__.py,sha256=u2Bwc79tkZTU5dMbhzzrPQi0RlFg22UgXc-m9K9G6wQ,242
68
- pyfemtet/opt/optimizer/optuna_optimizer/_optuna_attribute.py,sha256=cGI2jIqyBadoEC8C3jXFN0tl2tZpRCqu8vRq44Xy1xU,2206
69
- pyfemtet/opt/optimizer/optuna_optimizer/_optuna_optimizer.py,sha256=kFX_MUW3lWhHloe_26y1rYG6RVGZlwlBQR639d3FlIo,24494
68
+ pyfemtet/opt/optimizer/optuna_optimizer/_optuna_attribute.py,sha256=7eZsruVCGgMlcnf3a9Vf55FOEE-D7V777MJQajI12Cw,1842
69
+ pyfemtet/opt/optimizer/optuna_optimizer/_optuna_optimizer.py,sha256=CAFqKdb12rud6_akWKgxvCifIcG6DjTi5Tt7Cr2OoCs,28919
70
70
  pyfemtet/opt/optimizer/optuna_optimizer/_pof_botorch/__init__.py,sha256=BFbMNvdXqV9kl1h340pW2sq0-cwNFV5dfTo6UnNnX2M,179
71
71
  pyfemtet/opt/optimizer/optuna_optimizer/_pof_botorch/debug-pof-botorch.reccsv,sha256=K6oI9jPi_5yayhBrI9Tm1RX3PoWWKo74TOdqnaPsIy8,1746
72
72
  pyfemtet/opt/optimizer/optuna_optimizer/_pof_botorch/enable_nonlinear_constraint.py,sha256=FY0fIwiFvakEdeQNv13eb1YtTXKzu2lF67HL2Hfs06w,9814
73
- pyfemtet/opt/optimizer/optuna_optimizer/_pof_botorch/pof_botorch_sampler.py,sha256=gChJrOCQSQIwvoK-iIf-LDjDNNGKNXyJmWi-bCPQet4,46765
73
+ pyfemtet/opt/optimizer/optuna_optimizer/_pof_botorch/pof_botorch_sampler.py,sha256=yVQJAD1yJ-Q2aCRuYCCifejjFS0eZmE2IoDTnKQgMko,46822
74
74
  pyfemtet/opt/optimizer/optuna_optimizer/wat_ex14_parametric_jp.femprj,sha256=-M54MTNrV7muZWPm9Tjptd6HDdtgUFBsRroC6ytyqa0,180970
75
75
  pyfemtet/opt/optimizer/scipy_optimizer/__init__.py,sha256=oXx2JAVLvgz0WwIXAknuV4p2MupaiutYYvjI8hXcFwc,45
76
- pyfemtet/opt/optimizer/scipy_optimizer/_scipy_optimizer.py,sha256=41GF7eiyEbeYH1RLhybb-JpF9MIr_25UlzPhbbJyBUQ,12026
76
+ pyfemtet/opt/optimizer/scipy_optimizer/_scipy_optimizer.py,sha256=Og4DyD45nOmnBzrRYB8g_KSMyNH6tPNgItT3j7ThyMA,12901
77
77
  pyfemtet/opt/prediction/__init__.py,sha256=-XYo-l5YFjExMtqMKj1YUAhmGSQq_0YITS0qizj2Xbs,104
78
78
  pyfemtet/opt/prediction/_botorch_utils.py,sha256=KhPLY4JAPC6BDw_NA_KejzMYPCtGh-Yx1dc7PY1tYVA,3985
79
79
  pyfemtet/opt/prediction/_gpytorch_modules_extension.py,sha256=B_qUtFn06dQENOmUOObbCpkeASUKI5JpXROx8zYeaq0,5224
@@ -83,7 +83,7 @@ pyfemtet/opt/problem/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hS
83
83
  pyfemtet/opt/problem/problem.py,sha256=ohdZ450XH4YoFK4T9t52t8BSja6DpFTfMePQM1DdllU,9782
84
84
  pyfemtet/opt/problem/variable_manager/__init__.py,sha256=uzuraWUZfLzB3uZHIQHFL7uMxWvv7Oaf940zEozXtNY,476
85
85
  pyfemtet/opt/problem/variable_manager/_string_as_expression.py,sha256=aTJ9W9Gs6BS0Z_OsxWByJs9dAt32opD2_9913MCggPg,3626
86
- pyfemtet/opt/problem/variable_manager/_variable_manager.py,sha256=STqRDTnruV_WC-2tOejaIqVSVnoGJvVSo81R2PQBGvA,9818
86
+ pyfemtet/opt/problem/variable_manager/_variable_manager.py,sha256=XrcmFIfE4J_5zkz4Yx6j4QyDAuJX3M2zJ4wESf8oE1Q,12697
87
87
  pyfemtet/opt/visualization/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
88
88
  pyfemtet/opt/visualization/_create_wrapped_components.py,sha256=9AltJHr1DM6imZfpNp867rC-uAYqQ-emdgTLChKDrl8,2513
89
89
  pyfemtet/opt/visualization/history_viewer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -164,9 +164,9 @@ pyfemtet/opt/visualization/plotter/main_figure_creator.py,sha256=9RXz6Wt52MiSz3H
164
164
  pyfemtet/opt/visualization/plotter/pm_graph_creator.py,sha256=hUvvYeckMhkE1nH0FAOkXrA5K3A8PbfpxKYaYnBllB4,10864
165
165
  pyfemtet/opt/wat_ex14_parametric_jp.femprj,sha256=dMwQMt6yok_PbZLyxPYdmg5wJQwgQDZ4RhS76zdGLGk,177944
166
166
  pyfemtet/opt/worker_status.py,sha256=xSVW9lcw5jzYBwnmlVzk-1zCCyvmXVOH6EoRjqVbE9M,3605
167
- pyfemtet-1.0.0b0.dist-info/LICENSE,sha256=LWUL5LlMGjSRTvsalS8_fFuwS4VMw18fJSNWFwDK8pc,1060
168
- pyfemtet-1.0.0b0.dist-info/LICENSE_THIRD_PARTY.txt,sha256=8_9-cgzTpmeuCqItPZb9-lyAZcH2Qp9sZTU_hYuOZIQ,191
169
- pyfemtet-1.0.0b0.dist-info/METADATA,sha256=5ACU3bq6vcFxcOBZ5Krvh3VanMyfiAFL0gTfaQgJZck,3473
170
- pyfemtet-1.0.0b0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
171
- pyfemtet-1.0.0b0.dist-info/entry_points.txt,sha256=Tsb_l_8Z6pyyq2tRfuKiwfJUV3nq_cHoLS61foALtsg,134
172
- pyfemtet-1.0.0b0.dist-info/RECORD,,
167
+ pyfemtet-1.0.1.dist-info/LICENSE,sha256=LWUL5LlMGjSRTvsalS8_fFuwS4VMw18fJSNWFwDK8pc,1060
168
+ pyfemtet-1.0.1.dist-info/LICENSE_THIRD_PARTY.txt,sha256=8_9-cgzTpmeuCqItPZb9-lyAZcH2Qp9sZTU_hYuOZIQ,191
169
+ pyfemtet-1.0.1.dist-info/METADATA,sha256=8GuEhflweMHbq3Ap6e5ecnyPMj3eKxMgYxtEq7hegtw,3471
170
+ pyfemtet-1.0.1.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
171
+ pyfemtet-1.0.1.dist-info/entry_points.txt,sha256=Tsb_l_8Z6pyyq2tRfuKiwfJUV3nq_cHoLS61foALtsg,134
172
+ pyfemtet-1.0.1.dist-info/RECORD,,