DFO-LS 1.5.2__py3-none-any.whl → 1.5.4__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 DFO-LS might be problematic. Click here for more details.
- {DFO_LS-1.5.2.dist-info → DFO_LS-1.5.4.dist-info}/METADATA +7 -7
- DFO_LS-1.5.4.dist-info/RECORD +14 -0
- {DFO_LS-1.5.2.dist-info → DFO_LS-1.5.4.dist-info}/WHEEL +1 -1
- dfols/__init__.py +2 -2
- dfols/solver.py +54 -3
- dfols/util.py +14 -1
- DFO_LS-1.5.2.dist-info/RECORD +0 -14
- {DFO_LS-1.5.2.dist-info → DFO_LS-1.5.4.dist-info}/LICENSE.txt +0 -0
- {DFO_LS-1.5.2.dist-info → DFO_LS-1.5.4.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: DFO-LS
|
|
3
|
-
Version: 1.5.
|
|
3
|
+
Version: 1.5.4
|
|
4
4
|
Summary: A flexible derivative-free solver for (bound constrained) nonlinear least-squares minimization
|
|
5
5
|
Author-email: Lindon Roberts <lindon.roberts@sydney.edu.au>
|
|
6
6
|
Maintainer-email: Lindon Roberts <lindon.roberts@sydney.edu.au>
|
|
@@ -33,14 +33,14 @@ Description-Content-Type: text/x-rst
|
|
|
33
33
|
License-File: LICENSE.txt
|
|
34
34
|
Requires-Dist: setuptools
|
|
35
35
|
Requires-Dist: numpy
|
|
36
|
-
Requires-Dist: scipy
|
|
36
|
+
Requires-Dist: scipy>=1.11
|
|
37
37
|
Requires-Dist: pandas
|
|
38
38
|
Provides-Extra: dev
|
|
39
|
-
Requires-Dist: pytest
|
|
40
|
-
Requires-Dist: Sphinx
|
|
41
|
-
Requires-Dist: sphinx-rtd-theme
|
|
39
|
+
Requires-Dist: pytest; extra == "dev"
|
|
40
|
+
Requires-Dist: Sphinx; extra == "dev"
|
|
41
|
+
Requires-Dist: sphinx-rtd-theme; extra == "dev"
|
|
42
42
|
Provides-Extra: trustregion
|
|
43
|
-
Requires-Dist: trustregion
|
|
43
|
+
Requires-Dist: trustregion>=1.1; extra == "trustregion"
|
|
44
44
|
|
|
45
45
|
===================================================
|
|
46
46
|
DFO-LS: Derivative-Free Optimizer for Least-Squares
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
dfols/__init__.py,sha256=wOAEAlWyt7AEg1wLDbhf5cfdoL2cXGoR8BzF4_2rUMA,1621
|
|
2
|
+
dfols/controller.py,sha256=Jffyao_z7wcQf1WEQtv2smnNew8HXGguWuUPLbgVuCc,52487
|
|
3
|
+
dfols/diagnostic_info.py,sha256=kEcFCjD2rk39XRa90ocEaQvJWc0wj_ZPpQkOulVIM-k,6106
|
|
4
|
+
dfols/hessian.py,sha256=sExx4J4KoGwHItbthX2odosB2ONbQFvLdlcod7PIh4k,4262
|
|
5
|
+
dfols/model.py,sha256=1Npj3fJvMv66bKu_RIzLLI-2tyzPWOsKuyv-YUjcv2c,20711
|
|
6
|
+
dfols/params.py,sha256=GzJGO0TByH1X3B0NbLOCOqmYG8dRiKPKjjX7or_fOqI,18342
|
|
7
|
+
dfols/solver.py,sha256=psKOBi9F8PKdECyu7aS6fpzhN86DnYjFRvzX7XAFoPA,66788
|
|
8
|
+
dfols/trust_region.py,sha256=JbHLBDw7H88a3cIMuialh7kpMNGjL3Lp9JsjrBNpDWQ,28231
|
|
9
|
+
dfols/util.py,sha256=XYb42bc5X9nJtFT27sx6_tD_EcBbqOnCCjKy-1wLJxY,10725
|
|
10
|
+
DFO_LS-1.5.4.dist-info/LICENSE.txt,sha256=jOtLnuWt7d5Hsx6XXB2QxzrSe2sWWh3NgMfFRetluQM,35147
|
|
11
|
+
DFO_LS-1.5.4.dist-info/METADATA,sha256=Nm2dZQMPC3fa0U5MR_TXFpt_MuucKuMGSpAlWeco81c,8063
|
|
12
|
+
DFO_LS-1.5.4.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
|
13
|
+
DFO_LS-1.5.4.dist-info/top_level.txt,sha256=UfxRhaDN8HQx2_l17KbrDrERJ90OCN7VKkDMpYYbRLU,6
|
|
14
|
+
DFO_LS-1.5.4.dist-info/RECORD,,
|
dfols/__init__.py
CHANGED
|
@@ -39,9 +39,9 @@ alternative licensing.
|
|
|
39
39
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
|
40
40
|
|
|
41
41
|
# DFO-LS version
|
|
42
|
-
__version__ = '1.5.
|
|
42
|
+
__version__ = '1.5.4'
|
|
43
43
|
|
|
44
44
|
# Main solver & exit flags
|
|
45
45
|
from .solver import *
|
|
46
|
-
__all__ = ['solve']
|
|
46
|
+
__all__ = ['solve', 'OptimResults']
|
|
47
47
|
|
dfols/solver.py
CHANGED
|
@@ -32,6 +32,7 @@ import logging
|
|
|
32
32
|
from math import sqrt
|
|
33
33
|
import numpy as np
|
|
34
34
|
import os
|
|
35
|
+
import pandas as pd
|
|
35
36
|
import scipy.linalg as LA
|
|
36
37
|
import scipy.stats as STAT
|
|
37
38
|
import warnings
|
|
@@ -41,7 +42,7 @@ from .diagnostic_info import *
|
|
|
41
42
|
from .params import *
|
|
42
43
|
from .util import *
|
|
43
44
|
|
|
44
|
-
__all__ = ['solve']
|
|
45
|
+
__all__ = ['solve', 'OptimResults']
|
|
45
46
|
|
|
46
47
|
module_logger = logging.getLogger(__name__)
|
|
47
48
|
|
|
@@ -92,12 +93,60 @@ class OptimResults(object):
|
|
|
92
93
|
if self.diagnostic_info is not None:
|
|
93
94
|
output += "Diagnostic information available; check self.diagnostic_info\n"
|
|
94
95
|
output += "Solution xmin was evaluation point %g\n" % self.xmin_eval_num
|
|
95
|
-
if len(self.jacmin_eval_nums) < 100:
|
|
96
|
+
if self.jacmin_eval_nums is not None and len(self.jacmin_eval_nums) < 100:
|
|
96
97
|
output += "Approximate Jacobian formed using evaluation points %s\n" % str(self.jacmin_eval_nums)
|
|
98
|
+
elif self.jacmin_eval_nums is None:
|
|
99
|
+
output += "Approximate Jacobian not formed using problem information, disregard\n"
|
|
100
|
+
else:
|
|
101
|
+
output += "Not showing Jacobian evaluation points because it is too long; check self.jacmin_eval_nums\n"
|
|
97
102
|
output += "Exit flag = %g\n" % self.flag
|
|
98
103
|
output += "%s\n" % self.msg
|
|
99
104
|
output += "****************************\n"
|
|
100
105
|
return output
|
|
106
|
+
|
|
107
|
+
def to_dict(self, replace_nan=True):
|
|
108
|
+
# Convert to a serializable dict object suitable for saving in a json file
|
|
109
|
+
# If replace_nan=True, convert all NaN entries to None
|
|
110
|
+
soln_dict = {}
|
|
111
|
+
soln_dict['x'] = self.x.tolist() if self.x is not None else None
|
|
112
|
+
soln_dict['resid'] = self.resid.tolist() if self.resid is not None else None
|
|
113
|
+
soln_dict['obj'] = float(self.obj)
|
|
114
|
+
soln_dict['jacobian'] = self.jacobian.tolist() if self.jacobian is not None else None
|
|
115
|
+
soln_dict['nf'] = int(self.nf)
|
|
116
|
+
soln_dict['nx'] = int(self.nx)
|
|
117
|
+
soln_dict['nruns'] = int(self.nruns)
|
|
118
|
+
soln_dict['flag'] = int(self.flag)
|
|
119
|
+
soln_dict['msg'] = str(self.msg)
|
|
120
|
+
soln_dict['diagnostic_info'] = self.diagnostic_info.to_dict() if self.diagnostic_info is not None else None
|
|
121
|
+
soln_dict['xmin_eval_num'] = int(self.xmin_eval_num)
|
|
122
|
+
soln_dict['jacmin_eval_nums'] = self.jacmin_eval_nums.tolist() if self.jacmin_eval_nums is not None else None
|
|
123
|
+
if replace_nan:
|
|
124
|
+
return replace_nan_with_none(soln_dict)
|
|
125
|
+
else:
|
|
126
|
+
return soln_dict
|
|
127
|
+
|
|
128
|
+
@staticmethod
|
|
129
|
+
def from_dict(soln_dict):
|
|
130
|
+
# Take a dict object containing OptimResults information, and return the relevant OptimResults object
|
|
131
|
+
# Input soln_dict should come from soln.to_dict()
|
|
132
|
+
# Note: np.array(mylist, dtype=float) automatically converts None to NaN
|
|
133
|
+
x = np.array(soln_dict['x'], dtype=float) if soln_dict['x'] is not None else None
|
|
134
|
+
resid = np.array(soln_dict['resid'], dtype=float) if soln_dict['resid'] is not None else None
|
|
135
|
+
obj = soln_dict['obj']
|
|
136
|
+
jacobian = np.array(soln_dict['jacobian'], dtype=float) if soln_dict['jacobian'] is not None else None
|
|
137
|
+
nf = soln_dict['nf']
|
|
138
|
+
nx = soln_dict['nx']
|
|
139
|
+
nruns = soln_dict['nruns']
|
|
140
|
+
flag = soln_dict['flag']
|
|
141
|
+
msg = soln_dict['msg']
|
|
142
|
+
xmin_eval_num = soln_dict['xmin_eval_num']
|
|
143
|
+
jacmin_eval_nums = np.array(soln_dict['jacmin_eval_nums'], dtype=int) if soln_dict['jacmin_eval_nums'] is not None else None
|
|
144
|
+
|
|
145
|
+
soln = OptimResults(x, resid, obj, jacobian, nf, nx, nruns, flag, msg, xmin_eval_num, jacmin_eval_nums)
|
|
146
|
+
|
|
147
|
+
if soln_dict['diagnostic_info'] is not None:
|
|
148
|
+
soln.diagnostic_info = pd.DataFrame.from_dict(soln_dict['diagnostic_info'])
|
|
149
|
+
return soln
|
|
101
150
|
|
|
102
151
|
|
|
103
152
|
def solve_main(objfun, x0, argsf, xl, xu, projections, npt, rhobeg, rhoend, maxfun, nruns_so_far, nf_so_far, nx_so_far, nsamples, params,
|
|
@@ -148,7 +197,9 @@ def solve_main(objfun, x0, argsf, xl, xu, projections, npt, rhobeg, rhoend, maxf
|
|
|
148
197
|
exit_info = ExitInformation(EXIT_SUCCESS, "Objective is sufficiently small")
|
|
149
198
|
|
|
150
199
|
if exit_info is not None:
|
|
151
|
-
|
|
200
|
+
xmin_eval_num = 0
|
|
201
|
+
jacmin_eval_nums = np.array([0], dtype=int)
|
|
202
|
+
return x0, r0_avg, sumsq(r0_avg), None, num_samples_run, nf, nx, nruns_so_far+1, exit_info, diagnostic_info, xmin_eval_num, jacmin_eval_nums
|
|
152
203
|
|
|
153
204
|
else: # have old r0 information (e.g. from previous restart), use this instead
|
|
154
205
|
|
dfols/util.py
CHANGED
|
@@ -26,13 +26,14 @@ alternative licensing.
|
|
|
26
26
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
|
27
27
|
|
|
28
28
|
import logging
|
|
29
|
+
import math
|
|
29
30
|
import numpy as np
|
|
30
31
|
import scipy.linalg as LA
|
|
31
32
|
import sys
|
|
32
33
|
|
|
33
34
|
|
|
34
35
|
__all__ = ['sumsq', 'eval_least_squares_with_regularisation', 'model_value', 'random_orthog_directions_within_bounds',
|
|
35
|
-
'random_directions_within_bounds', 'apply_scaling', 'remove_scaling', 'pbox', 'pball', 'dykstra', 'qr_rank']
|
|
36
|
+
'random_directions_within_bounds', 'apply_scaling', 'remove_scaling', 'pbox', 'pball', 'dykstra', 'qr_rank', 'replace_nan_with_none']
|
|
36
37
|
|
|
37
38
|
module_logger = logging.getLogger(__name__)
|
|
38
39
|
|
|
@@ -268,3 +269,15 @@ def qr_rank(A,tol=1e-15):
|
|
|
268
269
|
D = np.abs(np.diag(R))
|
|
269
270
|
rank = np.sum(D > tol)
|
|
270
271
|
return rank, D
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
def replace_nan_with_none(d):
|
|
275
|
+
# Replace Nan values in a dict/list with None (used for JSON serializing of OptimResults object)
|
|
276
|
+
if isinstance(d, dict):
|
|
277
|
+
return {k: replace_nan_with_none(v) for k, v in d.items()}
|
|
278
|
+
elif isinstance(d, list):
|
|
279
|
+
return [replace_nan_with_none(i) for i in d]
|
|
280
|
+
elif isinstance(d, float) and math.isnan(d):
|
|
281
|
+
return None
|
|
282
|
+
else:
|
|
283
|
+
return d
|
DFO_LS-1.5.2.dist-info/RECORD
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
dfols/__init__.py,sha256=EGaYvogmtsNfmB_MVMFwglCwZbhl8O18rsOldwjIr5Q,1605
|
|
2
|
-
dfols/controller.py,sha256=Jffyao_z7wcQf1WEQtv2smnNew8HXGguWuUPLbgVuCc,52487
|
|
3
|
-
dfols/diagnostic_info.py,sha256=kEcFCjD2rk39XRa90ocEaQvJWc0wj_ZPpQkOulVIM-k,6106
|
|
4
|
-
dfols/hessian.py,sha256=sExx4J4KoGwHItbthX2odosB2ONbQFvLdlcod7PIh4k,4262
|
|
5
|
-
dfols/model.py,sha256=1Npj3fJvMv66bKu_RIzLLI-2tyzPWOsKuyv-YUjcv2c,20711
|
|
6
|
-
dfols/params.py,sha256=GzJGO0TByH1X3B0NbLOCOqmYG8dRiKPKjjX7or_fOqI,18342
|
|
7
|
-
dfols/solver.py,sha256=tvDdZgQ3AtybIZCTJf2DvGo6YvbV1NNACrzT2RUF000,63910
|
|
8
|
-
dfols/trust_region.py,sha256=JbHLBDw7H88a3cIMuialh7kpMNGjL3Lp9JsjrBNpDWQ,28231
|
|
9
|
-
dfols/util.py,sha256=efGVAKPb7YrHya1IOgyzacwa_h0u2jHHs5FhuxUlYDg,10282
|
|
10
|
-
DFO_LS-1.5.2.dist-info/LICENSE.txt,sha256=jOtLnuWt7d5Hsx6XXB2QxzrSe2sWWh3NgMfFRetluQM,35147
|
|
11
|
-
DFO_LS-1.5.2.dist-info/METADATA,sha256=eTT5r3VaND81vjaSdiW8AcUn6HsISxXAgV5UNXAHnBk,8069
|
|
12
|
-
DFO_LS-1.5.2.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
|
|
13
|
-
DFO_LS-1.5.2.dist-info/top_level.txt,sha256=UfxRhaDN8HQx2_l17KbrDrERJ90OCN7VKkDMpYYbRLU,6
|
|
14
|
-
DFO_LS-1.5.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|