invrs-opt 0.4.0__py3-none-any.whl → 0.5.0__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.
- invrs_opt/__init__.py +1 -1
- invrs_opt/lbfgsb/lbfgsb.py +68 -6
- {invrs_opt-0.4.0.dist-info → invrs_opt-0.5.0.dist-info}/METADATA +2 -2
- {invrs_opt-0.4.0.dist-info → invrs_opt-0.5.0.dist-info}/RECORD +7 -7
- {invrs_opt-0.4.0.dist-info → invrs_opt-0.5.0.dist-info}/WHEEL +1 -1
- {invrs_opt-0.4.0.dist-info → invrs_opt-0.5.0.dist-info}/LICENSE +0 -0
- {invrs_opt-0.4.0.dist-info → invrs_opt-0.5.0.dist-info}/top_level.txt +0 -0
invrs_opt/__init__.py
CHANGED
invrs_opt/lbfgsb/lbfgsb.py
CHANGED
@@ -29,16 +29,16 @@ LbfgsbState = Tuple[PyTree, PyTree, JaxLbfgsbDict]
|
|
29
29
|
# Task message prefixes for the underlying L-BFGS-B implementation.
|
30
30
|
TASK_START = b"START"
|
31
31
|
TASK_FG = b"FG"
|
32
|
+
TASK_CONVERGED = b"CONVERGENCE"
|
32
33
|
|
33
|
-
# Parameters which configure the state update step.
|
34
34
|
UPDATE_IPRINT = -1
|
35
|
-
UPDATE_PGTOL = 0.0
|
36
|
-
UPDATE_FACTR = 0.0
|
37
35
|
|
38
36
|
# Maximum value for the `maxcor` parameter in the L-BFGS-B scheme.
|
39
37
|
MAXCOR_MAX_VALUE = 100
|
40
38
|
MAXCOR_DEFAULT = 20
|
41
39
|
LINE_SEARCH_MAX_STEPS_DEFAULT = 100
|
40
|
+
FTOL_DEFAULT = 0.0
|
41
|
+
GTOL_DEFAULT = 0.0
|
42
42
|
|
43
43
|
# Maps bound scenarios to integers.
|
44
44
|
BOUNDS_MAP: Dict[Tuple[bool, bool], int] = {
|
@@ -54,6 +54,8 @@ FORTRAN_INT = scipy_lbfgsb.types.intvar.dtype
|
|
54
54
|
def lbfgsb(
|
55
55
|
maxcor: int = MAXCOR_DEFAULT,
|
56
56
|
line_search_max_steps: int = LINE_SEARCH_MAX_STEPS_DEFAULT,
|
57
|
+
ftol: float = FTOL_DEFAULT,
|
58
|
+
gtol: float = GTOL_DEFAULT,
|
57
59
|
) -> base.Optimizer:
|
58
60
|
"""Return an optimizer implementing the standard L-BFGS-B algorithm.
|
59
61
|
|
@@ -85,10 +87,17 @@ def lbfgsb(
|
|
85
87
|
While the algorithm can work with pytrees of jax arrays, numpy arrays can
|
86
88
|
also be used. Thus, e.g. the optimizer can directly be used with autograd.
|
87
89
|
|
90
|
+
When the optimization has converged (according to `ftol` or `gtol` criteria), the
|
91
|
+
optimizer simply returns the parameters which obtained the converged result. The
|
92
|
+
convergence can be queried by `is_converged(state)`.
|
93
|
+
|
88
94
|
Args:
|
89
95
|
maxcor: The maximum number of variable metric corrections used to define
|
90
96
|
the limited memory matrix, in the L-BFGS-B scheme.
|
91
97
|
line_search_max_steps: The maximum number of steps in the line search.
|
98
|
+
ftol: Tolerance for stopping criteria based on function values. See scipy
|
99
|
+
documentation for details.
|
100
|
+
gtol: Tolerance for stopping criteria based on gradient.
|
92
101
|
|
93
102
|
Returns:
|
94
103
|
The `base.Optimizer`.
|
@@ -96,6 +105,8 @@ def lbfgsb(
|
|
96
105
|
return transformed_lbfgsb(
|
97
106
|
maxcor=maxcor,
|
98
107
|
line_search_max_steps=line_search_max_steps,
|
108
|
+
ftol=ftol,
|
109
|
+
gtol=gtol,
|
99
110
|
transform_fn=lambda x: x,
|
100
111
|
initialize_latent_fn=lambda x: x,
|
101
112
|
)
|
@@ -105,6 +116,8 @@ def density_lbfgsb(
|
|
105
116
|
beta: float,
|
106
117
|
maxcor: int = MAXCOR_DEFAULT,
|
107
118
|
line_search_max_steps: int = LINE_SEARCH_MAX_STEPS_DEFAULT,
|
119
|
+
ftol: float = FTOL_DEFAULT,
|
120
|
+
gtol: float = GTOL_DEFAULT,
|
108
121
|
) -> base.Optimizer:
|
109
122
|
"""Return an L-BFGS-B optimizer with additional transforms for density arrays.
|
110
123
|
|
@@ -117,11 +130,18 @@ def density_lbfgsb(
|
|
117
130
|
and spacing parameters of the `DensityArray2D`. Where the bounds differ, the
|
118
131
|
density is scaled before the transform is applied, and then unscaled afterwards.
|
119
132
|
|
133
|
+
When the optimization has converged (according to `ftol` or `gtol` criteria), the
|
134
|
+
optimizer simply returns the parameters which obtained the converged result. The
|
135
|
+
convergence can be queried by `is_converged(state)`.
|
136
|
+
|
120
137
|
Args:
|
121
138
|
beta: Determines the steepness of the thresholding.
|
122
139
|
maxcor: The maximum number of variable metric corrections used to define
|
123
140
|
the limited memory matrix, in the L-BFGS-B scheme.
|
124
141
|
line_search_max_steps: The maximum number of steps in the line search.
|
142
|
+
ftol: Tolerance for stopping criteria based on function values. See scipy
|
143
|
+
documentation for details.
|
144
|
+
gtol: Tolerance for stopping criteria based on gradient.
|
125
145
|
|
126
146
|
Returns:
|
127
147
|
The `base.Optimizer`.
|
@@ -164,6 +184,8 @@ def density_lbfgsb(
|
|
164
184
|
return transformed_lbfgsb(
|
165
185
|
maxcor=maxcor,
|
166
186
|
line_search_max_steps=line_search_max_steps,
|
187
|
+
ftol=ftol,
|
188
|
+
gtol=gtol,
|
167
189
|
transform_fn=transform_fn,
|
168
190
|
initialize_latent_fn=initialize_latent_fn,
|
169
191
|
)
|
@@ -172,6 +194,8 @@ def density_lbfgsb(
|
|
172
194
|
def transformed_lbfgsb(
|
173
195
|
maxcor: int,
|
174
196
|
line_search_max_steps: int,
|
197
|
+
ftol: float,
|
198
|
+
gtol: float,
|
175
199
|
transform_fn: Callable[[PyTree], PyTree],
|
176
200
|
initialize_latent_fn: Callable[[PyTree], PyTree],
|
177
201
|
) -> base.Optimizer:
|
@@ -182,10 +206,17 @@ def transformed_lbfgsb(
|
|
182
206
|
`transform_fn`. In the simple case where this is just `lambda x: x` (i.e.
|
183
207
|
the identity), this is equivalent to the standard L-BFGS-B algorithm.
|
184
208
|
|
209
|
+
When the optimization has converged (according to `ftol` or `gtol` criteria), the
|
210
|
+
optimizer simply returns the parameters which obtained the converged result. The
|
211
|
+
convergence can be queried by `is_converged(state)`.
|
212
|
+
|
185
213
|
Args:
|
186
214
|
maxcor: The maximum number of variable metric corrections used to define
|
187
215
|
the limited memory matrix, in the L-BFGS-B scheme.
|
188
216
|
line_search_max_steps: The maximum number of steps in the line search.
|
217
|
+
ftol: Tolerance for stopping criteria based on function values. See scipy
|
218
|
+
documentation for details.
|
219
|
+
gtol: Tolerance for stopping criteria based on gradient.
|
189
220
|
transform_fn: Function which transforms the internal latent parameters to
|
190
221
|
the parameters returned by the optimizer.
|
191
222
|
initialize_latent_fn: Function which computes the initial latent parameters
|
@@ -218,6 +249,8 @@ def transformed_lbfgsb(
|
|
218
249
|
upper_bound=_bound_for_params(upper_bound, params),
|
219
250
|
maxcor=maxcor,
|
220
251
|
line_search_max_steps=line_search_max_steps,
|
252
|
+
ftol=ftol,
|
253
|
+
gtol=gtol,
|
221
254
|
)
|
222
255
|
latent_params = _to_pytree(scipy_lbfgsb_state.x, params)
|
223
256
|
return latent_params, scipy_lbfgsb_state.to_jax()
|
@@ -288,6 +321,11 @@ def transformed_lbfgsb(
|
|
288
321
|
)
|
289
322
|
|
290
323
|
|
324
|
+
def is_converged(state: LbfgsbState) -> jnp.ndarray:
|
325
|
+
"""Returns `True` if the optimization has converged."""
|
326
|
+
return state[2]["converged"]
|
327
|
+
|
328
|
+
|
291
329
|
# ------------------------------------------------------------------------------
|
292
330
|
# Helper functions.
|
293
331
|
# ------------------------------------------------------------------------------
|
@@ -392,8 +430,11 @@ def _example_state(params: PyTree, maxcor: int) -> PyTree:
|
|
392
430
|
float_params = tree_util.tree_map(lambda x: jnp.asarray(x, dtype=float), params)
|
393
431
|
example_jax_lbfgsb_state = dict(
|
394
432
|
x=jnp.zeros(n, dtype=float),
|
433
|
+
converged=jnp.asarray(False),
|
395
434
|
_maxcor=jnp.zeros((), dtype=int),
|
396
435
|
_line_search_max_steps=jnp.zeros((), dtype=int),
|
436
|
+
_ftol=jnp.zeros((), dtype=float),
|
437
|
+
_gtol=jnp.zeros((), dtype=float),
|
397
438
|
_wa=jnp.ones(_wa_size(n=n, maxcor=maxcor), dtype=float),
|
398
439
|
_iwa=jnp.ones(n * 3, dtype=jnp.int32), # Fortran int
|
399
440
|
_task=jnp.zeros(59, dtype=int),
|
@@ -443,10 +484,13 @@ class ScipyLbfgsbState:
|
|
443
484
|
"""
|
444
485
|
|
445
486
|
x: NDArray
|
487
|
+
converged: NDArray
|
446
488
|
# Private attributes correspond to internal variables in the `scipy.optimize.
|
447
489
|
# lbfgsb._minimize_lbfgsb` function.
|
448
490
|
_maxcor: int
|
449
491
|
_line_search_max_steps: int
|
492
|
+
_ftol: NDArray
|
493
|
+
_gtol: NDArray
|
450
494
|
_wa: NDArray
|
451
495
|
_iwa: NDArray
|
452
496
|
_task: NDArray
|
@@ -476,8 +520,11 @@ class ScipyLbfgsbState:
|
|
476
520
|
"""Generates a dictionary of jax arrays defining the state."""
|
477
521
|
return dict(
|
478
522
|
x=jnp.asarray(self.x),
|
523
|
+
converged=jnp.asarray(self.converged),
|
479
524
|
_maxcor=jnp.asarray(self._maxcor),
|
480
525
|
_line_search_max_steps=jnp.asarray(self._line_search_max_steps),
|
526
|
+
_ftol=jnp.asarray(self._ftol),
|
527
|
+
_gtol=jnp.asarray(self._gtol),
|
481
528
|
_wa=jnp.asarray(self._wa),
|
482
529
|
_iwa=jnp.asarray(self._iwa),
|
483
530
|
_task=_array_from_s60_str(self._task),
|
@@ -496,8 +543,11 @@ class ScipyLbfgsbState:
|
|
496
543
|
state_dict = copy.deepcopy(state_dict)
|
497
544
|
return ScipyLbfgsbState(
|
498
545
|
x=onp.asarray(state_dict["x"], dtype=onp.float64),
|
546
|
+
converged=onp.asarray(state_dict["converged"], dtype=bool),
|
499
547
|
_maxcor=int(state_dict["_maxcor"]),
|
500
548
|
_line_search_max_steps=int(state_dict["_line_search_max_steps"]),
|
549
|
+
_ftol=onp.asarray(state_dict["_ftol"], dtype=onp.float64),
|
550
|
+
_gtol=onp.asarray(state_dict["_gtol"], dtype=onp.float64),
|
501
551
|
_wa=onp.asarray(state_dict["_wa"], onp.float64),
|
502
552
|
_iwa=onp.asarray(state_dict["_iwa"], dtype=FORTRAN_INT),
|
503
553
|
_task=_s60_str_from_array(state_dict["_task"]),
|
@@ -518,6 +568,8 @@ class ScipyLbfgsbState:
|
|
518
568
|
upper_bound: ElementwiseBound,
|
519
569
|
maxcor: int,
|
520
570
|
line_search_max_steps: int,
|
571
|
+
ftol: float,
|
572
|
+
gtol: float,
|
521
573
|
) -> "ScipyLbfgsbState":
|
522
574
|
"""Initializes the `ScipyLbfgsbState` for `x0`.
|
523
575
|
|
@@ -528,6 +580,9 @@ class ScipyLbfgsbState:
|
|
528
580
|
maxcor: The maximum number of variable metric corrections used to define
|
529
581
|
the limited memory matrix, in the L-BFGS-B scheme.
|
530
582
|
line_search_max_steps: The maximum number of steps in the line search.
|
583
|
+
ftol: Tolerance for stopping criteria based on function values. See scipy
|
584
|
+
documentation for details.
|
585
|
+
gtol: Tolerance for stopping criteria based on gradient.
|
531
586
|
|
532
587
|
Returns:
|
533
588
|
The `ScipyLbfgsbState`.
|
@@ -558,8 +613,11 @@ class ScipyLbfgsbState:
|
|
558
613
|
wa_size = _wa_size(n=n, maxcor=maxcor)
|
559
614
|
state = ScipyLbfgsbState(
|
560
615
|
x=onp.array(x0, onp.float64),
|
616
|
+
converged=onp.asarray(False),
|
561
617
|
_maxcor=maxcor,
|
562
618
|
_line_search_max_steps=line_search_max_steps,
|
619
|
+
_ftol=onp.asarray(ftol, onp.float64),
|
620
|
+
_gtol=onp.asarray(gtol, onp.float64),
|
563
621
|
_wa=onp.zeros(wa_size, onp.float64),
|
564
622
|
_iwa=onp.zeros(3 * n, FORTRAN_INT),
|
565
623
|
_task=task,
|
@@ -582,12 +640,14 @@ class ScipyLbfgsbState:
|
|
582
640
|
grad: NDArray,
|
583
641
|
value: NDArray,
|
584
642
|
) -> None:
|
585
|
-
"""Performs an in-place update of the `ScipyLbfgsbState
|
643
|
+
"""Performs an in-place update of the `ScipyLbfgsbState` if not converged.
|
586
644
|
|
587
645
|
Args:
|
588
646
|
grad: The function gradient for the current `x`.
|
589
647
|
value: The scalar function value for the current `x`.
|
590
648
|
"""
|
649
|
+
if self.converged:
|
650
|
+
return
|
591
651
|
if grad.shape != self.x.shape:
|
592
652
|
raise ValueError(
|
593
653
|
f"`grad` must have the same shape as attribute `x`, but got shapes "
|
@@ -608,8 +668,8 @@ class ScipyLbfgsbState:
|
|
608
668
|
nbd=self._bound_type,
|
609
669
|
f=value,
|
610
670
|
g=grad,
|
611
|
-
factr=
|
612
|
-
pgtol=
|
671
|
+
factr=self._ftol / onp.finfo(float).eps,
|
672
|
+
pgtol=self._gtol,
|
613
673
|
wa=self._wa,
|
614
674
|
iwa=self._iwa,
|
615
675
|
task=self._task,
|
@@ -621,6 +681,8 @@ class ScipyLbfgsbState:
|
|
621
681
|
maxls=self._line_search_max_steps,
|
622
682
|
)
|
623
683
|
task_str = self._task.tobytes()
|
684
|
+
if task_str.startswith(TASK_CONVERGED):
|
685
|
+
self.converged = onp.asarray(True)
|
624
686
|
if task_str.startswith(TASK_FG):
|
625
687
|
break
|
626
688
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: invrs_opt
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.5.0
|
4
4
|
Summary: Algorithms for inverse design
|
5
5
|
Author-email: "Martin F. Schubert" <mfschubert@gmail.com>
|
6
6
|
Maintainer-email: "Martin F. Schubert" <mfschubert@gmail.com>
|
@@ -49,7 +49,7 @@ Requires-Dist: pytest-cov ; extra == 'tests'
|
|
49
49
|
Requires-Dist: pytest-subtests ; extra == 'tests'
|
50
50
|
|
51
51
|
# invrs-opt - Optimization algorithms for inverse design
|
52
|
-
`v0.
|
52
|
+
`v0.5.0`
|
53
53
|
|
54
54
|
## Overview
|
55
55
|
|
@@ -1,14 +1,14 @@
|
|
1
|
-
invrs_opt/__init__.py,sha256=
|
1
|
+
invrs_opt/__init__.py,sha256=SK2nHKhwT60br9D6W8gfJ5Kj11BR3fIdGAEVAJBgH1I,309
|
2
2
|
invrs_opt/base.py,sha256=dSX9QkMPzI8ROxy2cFNmMwk_89eQbk0rw94CzvLPQoY,907
|
3
3
|
invrs_opt/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4
4
|
invrs_opt/experimental/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
5
5
|
invrs_opt/experimental/client.py,sha256=td5o_YqqbcSypDrWCVrHGSoF8UxEdOLtKU0z9Dth9lA,4842
|
6
6
|
invrs_opt/experimental/labels.py,sha256=dQDAMPyFMV6mXnMy295z8Ap205DRdVzysXny_Be8FmY,562
|
7
7
|
invrs_opt/lbfgsb/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
8
|
-
invrs_opt/lbfgsb/lbfgsb.py,sha256=
|
8
|
+
invrs_opt/lbfgsb/lbfgsb.py,sha256=59OpEYmGH3ofDv6m8KQQob5mQJei2vTcm1COh7SAbgA,27896
|
9
9
|
invrs_opt/lbfgsb/transform.py,sha256=a_Saj9Wq4lvqCJBrg5L2Z9DZ2NVs1xqrHLqha90a9Ws,5971
|
10
|
-
invrs_opt-0.
|
11
|
-
invrs_opt-0.
|
12
|
-
invrs_opt-0.
|
13
|
-
invrs_opt-0.
|
14
|
-
invrs_opt-0.
|
10
|
+
invrs_opt-0.5.0.dist-info/LICENSE,sha256=ty6jHPvpyjHy6dbhnu6aDSY05bbl2jQTjnq9u1sBCfM,1078
|
11
|
+
invrs_opt-0.5.0.dist-info/METADATA,sha256=kV8T1uAmMnr0IDaNjq1SK8btKa_XlyHjapKOfti_MbY,3326
|
12
|
+
invrs_opt-0.5.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
13
|
+
invrs_opt-0.5.0.dist-info/top_level.txt,sha256=hOziS2uJ_NgwaW9yhtOfeuYnm1X7vobPBcp_6eVWKfM,10
|
14
|
+
invrs_opt-0.5.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|