spotoptim 2.0.0__tar.gz → 2.1.1__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.
- {spotoptim-2.0.0 → spotoptim-2.1.1}/PKG-INFO +1 -1
- {spotoptim-2.0.0 → spotoptim-2.1.1}/pyproject.toml +1 -1
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/SpotOptim.py +21 -41
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/optimizer/acquisition.py +112 -5
- {spotoptim-2.0.0 → spotoptim-2.1.1}/README.md +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/__init__.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/core/__init__.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/core/data.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/core/experiment.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/core/protocol.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/core/storage.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/data/__init__.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/data/base.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/data/diabetes.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/datasets/__init__.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/datasets/py.typed +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/datasets/test01.csv +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/datasets/test02.csv +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/datasets/test11.csv +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/eda/__init__.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/eda/plots.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/factor_analyzer/__init__.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/factor_analyzer/confirmatory_factor_analyzer.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/factor_analyzer/factor_analyzer.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/factor_analyzer/factor_analyzer_rotator.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/factor_analyzer/factor_analyzer_utils.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/function/__init__.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/function/cd_data.csv +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/function/forr08a.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/function/mo.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/function/remote.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/function/so.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/function/torch_objective.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/hyperparameters/__init__.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/hyperparameters/parameters.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/hyperparameters/repr_helpers.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/inspection/__init__.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/inspection/importance.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/inspection/predictions.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/mo/__init__.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/mo/mo_mm.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/mo/pareto.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/nn/__init__.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/nn/linear_regressor.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/nn/mlp.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/optimizer/__init__.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/optimizer/schedule_free.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/optimizer/wrapper.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/plot/__init__.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/plot/contour.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/plot/mo.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/plot/visualization.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/py.typed +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/reporting/__init__.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/reporting/analysis.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/reporting/results.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/sampling/__init__.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/sampling/design.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/sampling/effects.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/sampling/lhs.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/sampling/mm.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/surrogate/__init__.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/surrogate/kernels.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/surrogate/kriging.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/surrogate/mlp_surrogate.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/surrogate/nystroem.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/surrogate/pipeline.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/surrogate/simple_kriging.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/tricands/__init__.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/tricands/tricands.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/utils/__init__.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/utils/boundaries.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/utils/convert.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/utils/dimreduction.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/utils/eval.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/utils/file.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/utils/mapping.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/utils/ocba.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/utils/pca.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/utils/scaler.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/utils/serialization.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/utils/stats.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/utils/tensorboard.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/utils/transform.py +0 -0
- {spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/utils/variables.py +0 -0
|
@@ -89,10 +89,6 @@ class SpotOptimConfig:
|
|
|
89
89
|
acquisition_optimizer_kwargs (Optional[Dict[str, Any]]): Keyword arguments for the acquisition function optimizer.
|
|
90
90
|
args (Tuple): Arguments for the objective function.
|
|
91
91
|
kwargs (Optional[Dict[str, Any]]): Keyword arguments for the objective function.
|
|
92
|
-
metric_factorial (str): Distance metric used by a factor-aware Kriging surrogate for
|
|
93
|
-
nominal (categorical) variables. ``"hamming"`` (default) treats all distinct
|
|
94
|
-
factor levels as equidistant, which is correct for unordered factors.
|
|
95
|
-
Any scipy pairwise distance metric string is accepted.
|
|
96
92
|
|
|
97
93
|
|
|
98
94
|
Examples:
|
|
@@ -193,7 +189,6 @@ class SpotOptimConfig:
|
|
|
193
189
|
acquisition_optimizer_kwargs: Optional[Dict[str, Any]] = None
|
|
194
190
|
args: Tuple = ()
|
|
195
191
|
kwargs: Optional[Dict[str, Any]] = None
|
|
196
|
-
metric_factorial: str = "hamming"
|
|
197
192
|
|
|
198
193
|
def __post_init__(self):
|
|
199
194
|
if self.kwargs is None:
|
|
@@ -442,13 +437,6 @@ class SpotOptim(BaseEstimator):
|
|
|
442
437
|
* "cosine": Cosine distance.
|
|
443
438
|
* "correlation": Correlation distance.
|
|
444
439
|
* "canberra", "braycurtis", "sqeuclidean", etc.
|
|
445
|
-
metric_factorial (str, optional):
|
|
446
|
-
Distance metric used for nominal (factor) variables by a factor-aware
|
|
447
|
-
Kriging surrogate. ``"hamming"`` (default) treats all distinct factor
|
|
448
|
-
levels as equidistant, which is correct for unordered factors; any
|
|
449
|
-
scipy pairwise distance metric string is accepted. Only takes effect
|
|
450
|
-
when factor variables are present and ``surrogate`` is left as ``None``
|
|
451
|
-
(an order-agnostic Kriging is then built automatically).
|
|
452
440
|
|
|
453
441
|
Attributes:
|
|
454
442
|
X_ (ndarray): All evaluated points, shape (n_samples, n_features).
|
|
@@ -774,7 +762,6 @@ class SpotOptim(BaseEstimator):
|
|
|
774
762
|
acquisition_optimizer_kwargs: Optional[Dict[str, Any]] = None,
|
|
775
763
|
args: Tuple = (),
|
|
776
764
|
kwargs: Optional[Dict[str, Any]] = None,
|
|
777
|
-
metric_factorial: str = "hamming",
|
|
778
765
|
):
|
|
779
766
|
warnings.filterwarnings(warnings_filter)
|
|
780
767
|
|
|
@@ -853,7 +840,6 @@ class SpotOptim(BaseEstimator):
|
|
|
853
840
|
acquisition_optimizer_kwargs=acquisition_optimizer_kwargs,
|
|
854
841
|
args=args,
|
|
855
842
|
kwargs=kwargs,
|
|
856
|
-
metric_factorial=metric_factorial,
|
|
857
843
|
)
|
|
858
844
|
|
|
859
845
|
# Initialize State
|
|
@@ -1662,36 +1648,30 @@ class SpotOptim(BaseEstimator):
|
|
|
1662
1648
|
self._max_surrogate_points_list = None
|
|
1663
1649
|
self._active_max_surrogate_points = self.config.max_surrogate_points
|
|
1664
1650
|
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
)
|
|
1674
|
-
else:
|
|
1675
|
-
# No factor variables: use the standard GaussianProcessRegressor.
|
|
1676
|
-
kernel = ConstantKernel(1.0, (1e-2, 1e12)) * Matern(
|
|
1677
|
-
length_scale=1.0, length_scale_bounds=(1e-4, 1e2), nu=2.5
|
|
1678
|
-
)
|
|
1679
|
-
|
|
1680
|
-
# Determine optimizer for GPR
|
|
1681
|
-
optimizer = "fmin_l_bfgs_b" # Default used by sklearn
|
|
1682
|
-
if self.config.acquisition_optimizer_kwargs is not None:
|
|
1683
|
-
optimizer = partial(
|
|
1684
|
-
gpr_minimize_wrapper, **self.config.acquisition_optimizer_kwargs
|
|
1685
|
-
)
|
|
1651
|
+
# Default surrogate is the GaussianProcessRegressor for ALL problem
|
|
1652
|
+
# types. Factor variables are NOT auto-switched to a Kriging: the user
|
|
1653
|
+
# keeps full control over the surrogate (and is informed by
|
|
1654
|
+
# _validate_factor_surrogate_compat that a factor-aware
|
|
1655
|
+
# Kriging(metric_factorial="hamming") is available for nominal factors).
|
|
1656
|
+
kernel = ConstantKernel(1.0, (1e-2, 1e12)) * Matern(
|
|
1657
|
+
length_scale=1.0, length_scale_bounds=(1e-4, 1e2), nu=2.5
|
|
1658
|
+
)
|
|
1686
1659
|
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
optimizer=optimizer,
|
|
1660
|
+
# Determine optimizer for GPR
|
|
1661
|
+
optimizer = "fmin_l_bfgs_b" # Default used by sklearn
|
|
1662
|
+
if self.config.acquisition_optimizer_kwargs is not None:
|
|
1663
|
+
optimizer = partial(
|
|
1664
|
+
gpr_minimize_wrapper, **self.config.acquisition_optimizer_kwargs
|
|
1693
1665
|
)
|
|
1694
1666
|
|
|
1667
|
+
self.surrogate = GaussianProcessRegressor(
|
|
1668
|
+
kernel=kernel,
|
|
1669
|
+
n_restarts_optimizer=100,
|
|
1670
|
+
normalize_y=True,
|
|
1671
|
+
random_state=self.seed,
|
|
1672
|
+
optimizer=optimizer,
|
|
1673
|
+
)
|
|
1674
|
+
|
|
1695
1675
|
def _validate_factor_surrogate_compat(self) -> None:
|
|
1696
1676
|
"""Warn when factor variables are present but the surrogate is factor-blind.
|
|
1697
1677
|
|
|
@@ -117,6 +117,107 @@ def prepare_de_kwargs(optimizer: SpotOptimProtocol, x0=None):
|
|
|
117
117
|
return filtered_kwargs
|
|
118
118
|
|
|
119
119
|
|
|
120
|
+
# Normalized-space margin used to pull a warm-start x0 strictly inside the unit
|
|
121
|
+
# interval that scipy's DifferentialEvolutionSolver validates against. It must
|
|
122
|
+
# exceed the ~1e-16 rounding granularity of that rescaling by several orders of
|
|
123
|
+
# magnitude (robust) while staying negligible in parameter space (faithful).
|
|
124
|
+
_DE_X0_NORM_MARGIN = 1e-12
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def sanitize_de_x0(
|
|
128
|
+
x0: np.ndarray, bounds: Optional[List[Tuple[float, float]]]
|
|
129
|
+
) -> Optional[np.ndarray]:
|
|
130
|
+
"""Make a warm-start ``x0`` acceptable to scipy ``differential_evolution``.
|
|
131
|
+
|
|
132
|
+
``DifferentialEvolutionSolver`` does not validate ``x0`` against the raw box
|
|
133
|
+
``[lower, upper]``. It rescales every coordinate into a unit interval using
|
|
134
|
+
``scaled = (x0 - mid) * recip + 0.5`` with ``mid = (lower + upper) / 2`` and
|
|
135
|
+
``recip = 1 / |upper - lower|`` (``0`` when ``lower == upper``), then rejects
|
|
136
|
+
the whole run if any ``scaled`` falls outside ``[0, 1]``.
|
|
137
|
+
|
|
138
|
+
An incumbent that legitimately sits *on* a box bound (optimizers converge to
|
|
139
|
+
corners; clipped warm-starts and estimator defaults land exactly on a bound)
|
|
140
|
+
can rescale to a hair outside ``[0, 1]`` purely from floating-point rounding
|
|
141
|
+
— e.g. ``0.01`` on the bound ``(0.01, 100.0)`` normalizes to ``-1.1e-16``.
|
|
142
|
+
A raw-space nudge such as ``np.nextafter`` cannot repair this: one ULP at a
|
|
143
|
+
small bound (``~1.7e-18`` at ``0.01``) is far below the rounding granularity
|
|
144
|
+
of the rescaling at the span's magnitude, so the nudged value normalizes to
|
|
145
|
+
the same out-of-range number. The nudge is simply in the wrong metric.
|
|
146
|
+
|
|
147
|
+
This helper therefore clamps in scipy's *own* normalized metric and maps the
|
|
148
|
+
result back with scipy's exact inverse, leaving an already-valid ``x0``
|
|
149
|
+
untouched (bit-for-bit) and returning ``None`` only if a coordinate cannot be
|
|
150
|
+
made interior — in which case the caller drops the optional warm-start.
|
|
151
|
+
|
|
152
|
+
Args:
|
|
153
|
+
x0 (ndarray): Candidate warm-start point in internal (transformed) scale,
|
|
154
|
+
shape ``(n_features,)``.
|
|
155
|
+
bounds (list of tuple): Per-dimension ``(lower, upper)`` bounds in
|
|
156
|
+
internal scale, exactly as passed to ``differential_evolution``.
|
|
157
|
+
|
|
158
|
+
Returns:
|
|
159
|
+
Optional[ndarray]: ``x0`` unchanged when scipy already accepts it; a
|
|
160
|
+
minimally adjusted copy guaranteed to pass scipy's check; or ``None``
|
|
161
|
+
when no acceptable point exists — ``bounds`` is ``None``, ``x0`` is not
|
|
162
|
+
all finite, or a coordinate cannot be made interior. ``None`` simply
|
|
163
|
+
drops the optional warm-start for that infill.
|
|
164
|
+
|
|
165
|
+
Examples:
|
|
166
|
+
```{python}
|
|
167
|
+
import numpy as np
|
|
168
|
+
from spotoptim.optimizer.acquisition import sanitize_de_x0
|
|
169
|
+
|
|
170
|
+
# An incumbent exactly on the lower bound of a wide span: the raw value
|
|
171
|
+
# normalizes just below 0 and scipy would reject it.
|
|
172
|
+
bounds = [(0.01, 100.0)]
|
|
173
|
+
x0 = np.array([0.01])
|
|
174
|
+
fixed = sanitize_de_x0(x0, bounds)
|
|
175
|
+
lb, ub = 0.01, 100.0
|
|
176
|
+
mid, span = 0.5 * (lb + ub), abs(ub - lb)
|
|
177
|
+
scaled = (fixed[0] - mid) / span + 0.5
|
|
178
|
+
print(f"accepted by scipy: {0.0 <= scaled <= 1.0}")
|
|
179
|
+
print(f"distance from incumbent: {fixed[0] - 0.01:.2e}")
|
|
180
|
+
```
|
|
181
|
+
"""
|
|
182
|
+
if bounds is None:
|
|
183
|
+
return None
|
|
184
|
+
x0 = np.asarray(x0, dtype=float).ravel()
|
|
185
|
+
# A non-finite incumbent is pathological; never use it as a warm-start.
|
|
186
|
+
if not np.all(np.isfinite(x0)):
|
|
187
|
+
return None
|
|
188
|
+
lower = np.array([b[0] for b in bounds], dtype=float)
|
|
189
|
+
upper = np.array([b[1] for b in bounds], dtype=float)
|
|
190
|
+
|
|
191
|
+
# scipy's exact rescaling constants (see DifferentialEvolutionSolver.__init__
|
|
192
|
+
# and _unscale_parameters): note span uses |upper - lower|, so reversed
|
|
193
|
+
# bounds are handled identically to scipy.
|
|
194
|
+
mid = 0.5 * (lower + upper)
|
|
195
|
+
span = np.abs(lower - upper)
|
|
196
|
+
with np.errstate(divide="ignore", invalid="ignore"):
|
|
197
|
+
recip = np.where(span > 0.0, 1.0 / span, 0.0)
|
|
198
|
+
|
|
199
|
+
scaled = (x0 - mid) * recip + 0.5
|
|
200
|
+
|
|
201
|
+
# Fast path: scipy already accepts every coordinate -> leave x0 untouched so
|
|
202
|
+
# currently-working runs stay bit-for-bit identical.
|
|
203
|
+
if not np.any((scaled < 0.0) | (scaled > 1.0)):
|
|
204
|
+
return x0
|
|
205
|
+
|
|
206
|
+
# Clamp in scipy's normalized metric, then map back with its exact inverse
|
|
207
|
+
# (_scale_parameters: x = mid + (scaled - 0.5) * span).
|
|
208
|
+
scaled = np.clip(scaled, _DE_X0_NORM_MARGIN, 1.0 - _DE_X0_NORM_MARGIN)
|
|
209
|
+
x0_fixed = mid + (scaled - 0.5) * span
|
|
210
|
+
|
|
211
|
+
# Defense in depth: re-run scipy's exact check and drop x0 if any residual
|
|
212
|
+
# rounding still leaves a coordinate outside the unit interval. With finite
|
|
213
|
+
# x0 and finite bounds this is algebraically unreachable (the margin is far
|
|
214
|
+
# above the round-trip rounding error); it guards against future drift.
|
|
215
|
+
check = (x0_fixed - mid) * recip + 0.5
|
|
216
|
+
if not np.all(np.isfinite(x0_fixed)) or np.any((check < 0.0) | (check > 1.0)):
|
|
217
|
+
return None
|
|
218
|
+
return x0_fixed
|
|
219
|
+
|
|
220
|
+
|
|
120
221
|
def optimize_acquisition_de(optimizer: SpotOptimProtocol) -> np.ndarray:
|
|
121
222
|
"""Optimize using differential evolution.
|
|
122
223
|
|
|
@@ -140,11 +241,17 @@ def optimize_acquisition_de(optimizer: SpotOptimProtocol) -> np.ndarray:
|
|
|
140
241
|
|
|
141
242
|
if best_x is not None:
|
|
142
243
|
best_x = optimizer.transform_X(best_x)
|
|
143
|
-
#
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
244
|
+
# Make x0 acceptable to scipy's differential_evolution, which validates
|
|
245
|
+
# x0 in a NORMALIZED metric rather than the raw box. An incumbent on a
|
|
246
|
+
# box bound can otherwise be rejected by floating-point rounding; a
|
|
247
|
+
# raw-space nudge (np.nextafter) is in the wrong metric and too small to
|
|
248
|
+
# survive scipy's rescaling when |bound| << span (see sanitize_de_x0).
|
|
249
|
+
best_x = sanitize_de_x0(best_x, optimizer.bounds)
|
|
250
|
+
# Draw unconditionally within this branch so the RNG stream is identical
|
|
251
|
+
# whether or not sanitization succeeds; drop the optional warm-start if
|
|
252
|
+
# it could not be sanitized.
|
|
253
|
+
use_x0 = optimizer.rng.rand() < optimizer.de_x0_prob
|
|
254
|
+
best_X = best_x if (best_x is not None and use_x0) else None
|
|
148
255
|
else:
|
|
149
256
|
best_X = None
|
|
150
257
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/factor_analyzer/confirmatory_factor_analyzer.py
RENAMED
|
File without changes
|
|
File without changes
|
{spotoptim-2.0.0 → spotoptim-2.1.1}/src/spotoptim/factor_analyzer/factor_analyzer_rotator.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|