DFO-LS 1.5.3__tar.gz → 1.5.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of DFO-LS might be problematic. Click here for more details.

@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: DFO-LS
3
- Version: 1.5.3
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>
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: DFO-LS
3
- Version: 1.5.3
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>
@@ -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.3'
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
 
@@ -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,
@@ -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
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