DFO-LS 1.2.1__py3-none-any.whl → 1.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.
Potentially problematic release.
This version of DFO-LS might be problematic. Click here for more details.
- {DFO_LS-1.2.1.dist-info → DFO_LS-1.5.0.dist-info}/METADATA +66 -60
- DFO_LS-1.5.0.dist-info/RECORD +14 -0
- {DFO_LS-1.2.1.dist-info → DFO_LS-1.5.0.dist-info}/WHEEL +1 -1
- {DFO_LS-1.2.1.dist-info → DFO_LS-1.5.0.dist-info}/top_level.txt +0 -0
- dfols/__init__.py +4 -5
- dfols/controller.py +274 -59
- dfols/hessian.py +1 -1
- dfols/model.py +64 -33
- dfols/params.py +32 -2
- dfols/solver.py +156 -91
- dfols/trust_region.py +237 -7
- dfols/util.py +71 -10
- DFO_LS-1.2.1.dist-info/RECORD +0 -16
- DFO_LS-1.2.1.dist-info/zip-safe +0 -1
- dfols/version.py +0 -25
- {DFO_LS-1.2.1.dist-info → DFO_LS-1.5.0.dist-info}/LICENSE.txt +0 -0
dfols/trust_region.py
CHANGED
|
@@ -11,6 +11,15 @@ produces a new vector d which (approximately) solves the trust region subproblem
|
|
|
11
11
|
The other outputs: gnew is the gradient of the model at d, and crvmin has
|
|
12
12
|
information about the curvature of the model at the solution.
|
|
13
13
|
|
|
14
|
+
For handling arbitrary constraints, the call is
|
|
15
|
+
d, gnew, crvmin = ctrsbox(xopt, g, H, projections, delta)
|
|
16
|
+
which produces a new vector d approximately solving the constrained trust region subproblem:
|
|
17
|
+
min_{d} g'*d + 0.5*d'*H*d
|
|
18
|
+
s.t. ||d|| <= delta
|
|
19
|
+
xopt + d is feasible w.r.t. the constraint set C
|
|
20
|
+
The other outputs: gnew is the gradient of the model at d, and crvmin has
|
|
21
|
+
information about the curvature of the model at the solution.
|
|
22
|
+
|
|
14
23
|
We also provide a function for maximising the absolute value of a linear function
|
|
15
24
|
inside a similar trust region - this is useful for geometry steps.
|
|
16
25
|
The call
|
|
@@ -20,9 +29,16 @@ solves
|
|
|
20
29
|
s.t. lower <= x <= upper
|
|
21
30
|
||x-xbase|| <= Delta
|
|
22
31
|
With this value, the variable d=x-xbase solves the problem
|
|
23
|
-
|
|
32
|
+
min_d abs(c + g' * d)
|
|
24
33
|
s.t. lower <= xbase + d <= upper
|
|
25
34
|
||d|| <= delta
|
|
35
|
+
Again, we have a version of this for handling arbitrary constraints
|
|
36
|
+
The call
|
|
37
|
+
x = ctrsbox_geometry(xbase, c, g, projections, Delta)
|
|
38
|
+
Solves
|
|
39
|
+
min_d abs(c + g' * d)
|
|
40
|
+
s.t. xbase + d is feasible w.r.t. the constraint set C
|
|
41
|
+
||d|| <= delta
|
|
26
42
|
|
|
27
43
|
Notes
|
|
28
44
|
----
|
|
@@ -54,7 +70,7 @@ alternative licensing.
|
|
|
54
70
|
# Ensure compatibility with Python 2
|
|
55
71
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
|
56
72
|
|
|
57
|
-
from math import sqrt
|
|
73
|
+
from math import sqrt, ceil
|
|
58
74
|
import numpy as np
|
|
59
75
|
try:
|
|
60
76
|
import trustregion
|
|
@@ -63,14 +79,157 @@ except ImportError:
|
|
|
63
79
|
# Fall back to Python implementation
|
|
64
80
|
USE_FORTRAN = False
|
|
65
81
|
|
|
82
|
+
from .util import dykstra, pball, pbox, sumsq, model_value, remove_scaling
|
|
66
83
|
|
|
67
|
-
|
|
84
|
+
__all__ = ['ctrsbox_sfista', 'ctrsbox_pgd', 'ctrsbox_geometry', 'trsbox', 'trsbox_geometry']
|
|
68
85
|
|
|
86
|
+
ZERO_THRESH = 1e-14
|
|
69
87
|
|
|
70
|
-
|
|
88
|
+
def ctrsbox_sfista(xopt, g, H, projections, delta, h, L_h, prox_uh, argsh=(), argsprox=(), func_tol=1e-3, max_iters=500, d_max_iters=100, d_tol=1e-10, use_fortran=USE_FORTRAN, scaling_changes=None, sfista_iters_scale=1.0):
|
|
89
|
+
n = xopt.size
|
|
90
|
+
assert xopt.shape == (n,), "xopt has wrong shape (should be vector)"
|
|
91
|
+
assert g.shape == (n,), "g and xopt have incompatible sizes"
|
|
92
|
+
assert len(H.shape) == 2, "H must be a matrix"
|
|
93
|
+
assert H.shape == (n,n), "H and xopt have incompatible sizes"
|
|
94
|
+
assert np.allclose(H, H.T), "H must be symmetric"
|
|
95
|
+
assert delta > 0.0, "delta must be strictly positive"
|
|
71
96
|
|
|
72
|
-
|
|
97
|
+
# Initialization
|
|
98
|
+
d = np.zeros(n) # start with zero vector
|
|
99
|
+
y = np.zeros(n)
|
|
100
|
+
t = 1
|
|
101
|
+
k_H = np.linalg.norm(H, 2)
|
|
102
|
+
crvmin = -1.0
|
|
103
|
+
|
|
104
|
+
# Number of iterations & smoothing parameter, from Theorem 10.57 in
|
|
105
|
+
# [A. Beck. First-order methods in optimization, SIAM, 2017]
|
|
106
|
+
# We do not use the values of k and mu given in the theorem statement, but rather the intermediate
|
|
107
|
+
# results on p313 (K1 for number of iterations, and the immediate next line for mu)
|
|
108
|
+
# Note: in the book's notation, Gamma=delta^2, alpha=1, beta=L_h^2/2, Lf=k_H [alpha and beta from Thm 10.51]
|
|
109
|
+
try:
|
|
110
|
+
MAX_LOOP_ITERS = ceil(sfista_iters_scale * delta * (L_h+sqrt(L_h*L_h+2*k_H*func_tol)) / func_tol)
|
|
111
|
+
MAX_LOOP_ITERS = min(MAX_LOOP_ITERS, max_iters)
|
|
112
|
+
except ValueError:
|
|
113
|
+
MAX_LOOP_ITERS = max_iters
|
|
114
|
+
u = 2 * delta / (MAX_LOOP_ITERS * L_h) # smoothing parameter
|
|
115
|
+
# u = 2 * func_tol / (L_h ** 2 + L_h * sqrt(L_h ** 2 + 2 * k_H * func_tol)) # the above choice works better in practice
|
|
116
|
+
|
|
117
|
+
def gradient_Fu(xopt, g, H, u, prox_uh, d):
|
|
118
|
+
# Calculate gradient_Fu,
|
|
119
|
+
# where Fu(d) := g(d) + h_u(d) and h_u(d) is a 1/u-smooth approximation of h.
|
|
120
|
+
# We assume that h is globally Lipschitz continous with constant L_h,
|
|
121
|
+
# then we can let h_u(d) be the Moreau Envelope M_h_u(d) of h.
|
|
122
|
+
return g + H @ d + (xopt + d - prox_uh(remove_scaling(xopt + d, scaling_changes), u, *argsprox)) / u
|
|
123
|
+
|
|
124
|
+
# Lipschitz constant of gradient_Fu
|
|
125
|
+
l = k_H + 1 / u
|
|
126
|
+
|
|
127
|
+
# trust region is a ball of radius delta around xopt
|
|
128
|
+
trproj = lambda w: pball(w, xopt, delta)
|
|
129
|
+
|
|
130
|
+
# combine trust region constraints with user-entered constraints
|
|
131
|
+
P = list(projections) # make a copy of the projections list
|
|
132
|
+
P.append(trproj)
|
|
133
|
+
def proj(d0):
|
|
134
|
+
p = dykstra(P, xopt+d0, max_iter=d_max_iters, tol=d_tol)
|
|
135
|
+
# we want the step only, so we subtract xopt
|
|
136
|
+
# from the new point: proj(xk+d) - xk
|
|
137
|
+
return p - xopt
|
|
138
|
+
|
|
139
|
+
# general step
|
|
140
|
+
model_value_best = model_value(g, H, d, xopt, h, argsh, scaling_changes)
|
|
141
|
+
d_best = d.copy()
|
|
142
|
+
for k in range(MAX_LOOP_ITERS):
|
|
143
|
+
prev_d = d.copy()
|
|
144
|
+
prev_t = t
|
|
145
|
+
# gradient_Fu at y
|
|
146
|
+
g_Fu = gradient_Fu(xopt, g, H, u, prox_uh, d, *argsprox)
|
|
147
|
+
|
|
148
|
+
# main update step
|
|
149
|
+
d = proj(y - g_Fu / l)
|
|
150
|
+
new_model_value = model_value(g, H, d, xopt, h, argsh, scaling_changes)
|
|
151
|
+
if new_model_value < model_value_best:
|
|
152
|
+
d_best = d.copy()
|
|
153
|
+
model_value_best = new_model_value
|
|
154
|
+
|
|
155
|
+
# update true gradient
|
|
156
|
+
# gnew is the gradient of the smoothed function
|
|
157
|
+
gnew = gradient_Fu(xopt, g, H, u, prox_uh, d, *argsprox)
|
|
158
|
+
|
|
159
|
+
# update CRVMIN
|
|
160
|
+
crv = d.dot(H).dot(d)/sumsq(d) if sumsq(d) >= ZERO_THRESH else crvmin
|
|
161
|
+
crvmin = min(crvmin, crv) if crvmin != -1.0 else crv
|
|
162
|
+
|
|
163
|
+
# momentum update
|
|
164
|
+
t = (1 + sqrt(1 + 4*t*t)) / 2
|
|
165
|
+
y = d + (prev_t - 1) * (d - prev_d) / t
|
|
166
|
+
return d, gnew, crvmin
|
|
167
|
+
|
|
168
|
+
def ctrsbox_pgd(xopt, g, H, projections, delta, d_max_iters=100, d_tol=1e-10, use_fortran=USE_FORTRAN):
|
|
169
|
+
n = xopt.size
|
|
170
|
+
assert xopt.shape == (n,), "xopt has wrong shape (should be vector)"
|
|
171
|
+
assert g.shape == (n,), "g and xopt have incompatible sizes"
|
|
172
|
+
assert len(H.shape) == 2, "H must be a matrix"
|
|
173
|
+
assert H.shape == (n,n), "H and xopt have incompatible sizes"
|
|
174
|
+
assert np.allclose(H, H.T), "H must be symmetric"
|
|
175
|
+
assert delta > 0.0, "delta must be strictly positive"
|
|
176
|
+
|
|
177
|
+
d = np.zeros((n,))
|
|
178
|
+
gnew = g.copy()
|
|
179
|
+
gy = g.copy()
|
|
180
|
+
crvmin = -1.0
|
|
181
|
+
y = d.copy()
|
|
182
|
+
eta = 1.2 # L backtrack scaling factor
|
|
183
|
+
t = 1
|
|
184
|
+
|
|
185
|
+
# Initial guess of L is norm(Hessian)
|
|
186
|
+
L = np.linalg.norm(H, 2)
|
|
187
|
+
|
|
188
|
+
# trust region is a ball of radius delta around xopt
|
|
189
|
+
trproj = lambda w: pball(w, xopt, delta)
|
|
190
|
+
|
|
191
|
+
# combine trust region constraints with user-entered constraints
|
|
192
|
+
P = list(projections) # make a copy of the projections list
|
|
193
|
+
P.append(trproj)
|
|
194
|
+
def proj(d0):
|
|
195
|
+
p = dykstra(P, xopt+d0, max_iter=d_max_iters, tol=d_tol)
|
|
196
|
+
# we want the step only, so we subtract xopt
|
|
197
|
+
# from the new point: proj(xk+d) - xk
|
|
198
|
+
return p - xopt
|
|
199
|
+
|
|
200
|
+
MAX_LOOP_ITERS = 100 * n ** 2
|
|
201
|
+
|
|
202
|
+
# projected GD loop
|
|
203
|
+
for ii in range(MAX_LOOP_ITERS):
|
|
204
|
+
w = y - (1/L)*gy
|
|
205
|
+
prev_d = d.copy()
|
|
206
|
+
d = proj(w)
|
|
207
|
+
|
|
208
|
+
# size of step taken
|
|
209
|
+
s = d - prev_d
|
|
210
|
+
stplen = np.linalg.norm(s)
|
|
73
211
|
|
|
212
|
+
# update true gradient
|
|
213
|
+
gnew += H.dot(s)
|
|
214
|
+
|
|
215
|
+
# update CRVMIN
|
|
216
|
+
crv = s.dot(H).dot(s)/sumsq(s) if sumsq(s) >= ZERO_THRESH else crvmin
|
|
217
|
+
crvmin = min(crvmin, crv) if crvmin != -1.0 else crv
|
|
218
|
+
|
|
219
|
+
# exit condition
|
|
220
|
+
if stplen <= ZERO_THRESH:
|
|
221
|
+
break
|
|
222
|
+
|
|
223
|
+
# momentum update
|
|
224
|
+
prev_t = t
|
|
225
|
+
t = (1 + np.sqrt(1 + 4 * t ** 2))/2
|
|
226
|
+
prev_y = y.copy()
|
|
227
|
+
y = d + s*(prev_t - 1)/t
|
|
228
|
+
|
|
229
|
+
# update gradient w.r.t y
|
|
230
|
+
gy += H.dot(y - prev_y)
|
|
231
|
+
|
|
232
|
+
return d, gnew, crvmin
|
|
74
233
|
|
|
75
234
|
def trsbox(xopt, g, H, sl, su, delta, use_fortran=USE_FORTRAN):
|
|
76
235
|
if use_fortran:
|
|
@@ -103,7 +262,7 @@ def trsbox(xopt, g, H, sl, su, delta, use_fortran=USE_FORTRAN):
|
|
|
103
262
|
iterc = 0
|
|
104
263
|
nact = 0 # number of fixed variables
|
|
105
264
|
|
|
106
|
-
xbdi = np.zeros((n,), dtype=
|
|
265
|
+
xbdi = np.zeros((n,), dtype=int) # fix x_i at bounds? [values -1, 0, 1]
|
|
107
266
|
xbdi[(xopt <= sl) & (g >= 0.0)] = -1
|
|
108
267
|
xbdi[(xopt >= su) & (g <= 0.0)] = 1
|
|
109
268
|
|
|
@@ -405,8 +564,63 @@ def ball_step(x0, g, Delta):
|
|
|
405
564
|
if sqrt(gsqnorm) < ZERO_THRESH: # Error catching: if g=0, make no step
|
|
406
565
|
return 0.0
|
|
407
566
|
else:
|
|
408
|
-
|
|
567
|
+
# Sqrt had negative input on prob 46 in OG DFOLS with noise
|
|
568
|
+
# print("Inside of the sqrt:", gdotx0**2 + gsqnorm*(Delta**2 - x0sqnorm))
|
|
569
|
+
# Got Inside of the sqrt: -3.608971127647144e-42
|
|
570
|
+
# Added max(0,...) here
|
|
571
|
+
return (sqrt(np.maximum(0,gdotx0**2 + gsqnorm*(Delta**2 - x0sqnorm))) - gdotx0) / gsqnorm
|
|
572
|
+
|
|
573
|
+
def ctrsbox_linear(xbase, g, projections, Delta, d_max_iters=100, d_tol=1e-10, use_fortran=USE_FORTRAN):
|
|
574
|
+
# Solve the convex program:
|
|
575
|
+
# min_d g' * d
|
|
576
|
+
# s.t. xbase + d is feasible w.r.t. constraint set C
|
|
577
|
+
# ||d||^2 <= Delta^2
|
|
578
|
+
|
|
579
|
+
n = g.size
|
|
580
|
+
d = np.zeros((n,))
|
|
581
|
+
y = d.copy()
|
|
582
|
+
t = 1
|
|
583
|
+
dirn = -g
|
|
584
|
+
cons_dirns = []
|
|
585
|
+
|
|
586
|
+
# If g[i] = 0, never step along this direction
|
|
587
|
+
constant_directions = np.where(np.abs(dirn) < ZERO_THRESH)[0]
|
|
588
|
+
dirn[constant_directions] = 0.0
|
|
589
|
+
|
|
590
|
+
# trust region is a ball of radius delta centered around xbase
|
|
591
|
+
trproj = lambda w: pball(w, xbase, Delta)
|
|
409
592
|
|
|
593
|
+
# combine trust region constraints with user-entered constraints
|
|
594
|
+
P = list(projections) # make a copy of the projections list
|
|
595
|
+
P.append(trproj)
|
|
596
|
+
def proj(d0):
|
|
597
|
+
p = dykstra(P, xbase + d0, max_iter=d_max_iters, tol=d_tol)
|
|
598
|
+
# we want the step only, so we subtract
|
|
599
|
+
# xbase from the new point: proj(xk + d) - xk
|
|
600
|
+
return p - xbase
|
|
601
|
+
|
|
602
|
+
MAX_LOOP_ITERS = 100 * n ** 2
|
|
603
|
+
|
|
604
|
+
# projected GD loop
|
|
605
|
+
for ii in range(MAX_LOOP_ITERS):
|
|
606
|
+
w = y + dirn
|
|
607
|
+
prev_d = d.copy()
|
|
608
|
+
d = proj(w)
|
|
609
|
+
|
|
610
|
+
s = d - prev_d
|
|
611
|
+
stplen = np.linalg.norm(s)
|
|
612
|
+
|
|
613
|
+
# exit condition
|
|
614
|
+
if stplen <= ZERO_THRESH:
|
|
615
|
+
break
|
|
616
|
+
|
|
617
|
+
# 'momentum' update
|
|
618
|
+
prev_t = t
|
|
619
|
+
t = (1 + np.sqrt(1 + 4 * t ** 2))/2
|
|
620
|
+
prev_y = y.copy()
|
|
621
|
+
y = d + s*(prev_t - 1)/t
|
|
622
|
+
|
|
623
|
+
return d
|
|
410
624
|
|
|
411
625
|
def trsbox_linear(g, a_in, b_in, Delta, use_fortran=USE_FORTRAN):
|
|
412
626
|
# Solve the convex program:
|
|
@@ -466,6 +680,22 @@ def trsbox_linear(g, a_in, b_in, Delta, use_fortran=USE_FORTRAN):
|
|
|
466
680
|
dirn[idx_hit] = 0.0 # no more searching this direction
|
|
467
681
|
return x
|
|
468
682
|
|
|
683
|
+
def ctrsbox_geometry(xbase, c, g, projections, Delta, d_max_iters=100, d_tol=1e-10, use_fortran=USE_FORTRAN):
|
|
684
|
+
# Given a Lagrange polynomial defined by: L(x) = c + g' * (x - xbase)
|
|
685
|
+
# Maximise |L(x)| in a box + trust region - that is, solve:
|
|
686
|
+
# max_x abs(c + g' * (x - xbase))
|
|
687
|
+
# s.t. x is feasible w.r.t constraint set C
|
|
688
|
+
# ||x-xbase|| <= Delta
|
|
689
|
+
# Setting s = x-xbase (or x = xbase + s), this is equivalent to:
|
|
690
|
+
# max_s abs(c + g' * s)
|
|
691
|
+
# s.t. xbase + s is is feasible w.r.t constraint set C
|
|
692
|
+
# ||s|| <= Delta
|
|
693
|
+
smin = ctrsbox_linear(xbase, g, projections, Delta, d_max_iters=100, d_tol=1e-10, use_fortran=use_fortran) # minimise g' * s
|
|
694
|
+
smax = ctrsbox_linear(xbase, -g, projections, Delta, d_max_iters=100, d_tol=1e-10, use_fortran=use_fortran) # maximise g' * s
|
|
695
|
+
if abs(c + np.dot(g, smin)) >= abs(c + np.dot(g, smax)): # choose the one with largest absolute value
|
|
696
|
+
return smin
|
|
697
|
+
else:
|
|
698
|
+
return smax
|
|
469
699
|
|
|
470
700
|
def trsbox_geometry(xbase, c, g, lower, upper, Delta, use_fortran=USE_FORTRAN):
|
|
471
701
|
# Given a Lagrange polynomial defined by: L(x) = c + g' * (x - xbase)
|
dfols/util.py
CHANGED
|
@@ -27,11 +27,14 @@ from __future__ import absolute_import, division, print_function, unicode_litera
|
|
|
27
27
|
|
|
28
28
|
import logging
|
|
29
29
|
import numpy as np
|
|
30
|
+
import scipy.linalg as LA
|
|
30
31
|
import sys
|
|
31
32
|
|
|
32
33
|
|
|
33
|
-
__all__ = ['sumsq', '
|
|
34
|
-
'random_directions_within_bounds', 'apply_scaling', 'remove_scaling']
|
|
34
|
+
__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
|
+
|
|
37
|
+
module_logger = logging.getLogger(__name__)
|
|
35
38
|
|
|
36
39
|
|
|
37
40
|
def sumsq(x):
|
|
@@ -44,9 +47,9 @@ def sumsq(x):
|
|
|
44
47
|
return np.dot(x, x)
|
|
45
48
|
|
|
46
49
|
|
|
47
|
-
def
|
|
50
|
+
def eval_least_squares_with_regularisation(objfun, x, h=None, argsf=(), argsh=(), verbose=True, eval_num=0, pt_num=0, full_x_thresh=6, check_for_overflow=True):
|
|
48
51
|
# Evaluate least squares function
|
|
49
|
-
fvec = objfun(x, *
|
|
52
|
+
fvec = objfun(x, *argsf)
|
|
50
53
|
|
|
51
54
|
if check_for_overflow:
|
|
52
55
|
try:
|
|
@@ -59,20 +62,31 @@ def eval_least_squares_objective(objfun, x, args=(), verbose=True, eval_num=0, p
|
|
|
59
62
|
else:
|
|
60
63
|
f = sumsq(fvec)
|
|
61
64
|
|
|
65
|
+
# objective = least-squares + regularisation
|
|
66
|
+
obj = f
|
|
67
|
+
if h is not None:
|
|
68
|
+
# Evaluate regularisation term
|
|
69
|
+
hvalue = h(x, *argsh)
|
|
70
|
+
obj = f + hvalue
|
|
71
|
+
|
|
62
72
|
if verbose:
|
|
63
73
|
if len(x) < full_x_thresh:
|
|
64
|
-
|
|
74
|
+
module_logger.info("Function eval %i at point %i has obj = %.15g at x = " % (eval_num, pt_num, obj) + str(x))
|
|
65
75
|
else:
|
|
66
|
-
|
|
76
|
+
module_logger.info("Function eval %i at point %i has obj = %.15g at x = [...]" % (eval_num, pt_num, obj))
|
|
67
77
|
|
|
68
|
-
return fvec,
|
|
78
|
+
return fvec, obj
|
|
69
79
|
|
|
70
80
|
|
|
71
|
-
def model_value(g, H, s):
|
|
72
|
-
# Calculate model value (s^T * g + 0.5* s^T * H * s) = s^T * (gopt + 0.5 * H*s)
|
|
81
|
+
def model_value(g, H, s, xopt=(), h=None,argsh=(), scaling_changes=None):
|
|
82
|
+
# Calculate model value (s^T * g + 0.5* s^T * H * s) + h(xopt + s) = s^T * (gopt + 0.5 * H*s) + h(xopt + s)
|
|
73
83
|
assert g.shape == s.shape, "g and s have incompatible sizes"
|
|
74
84
|
Hs = H.dot(s)
|
|
75
|
-
|
|
85
|
+
rtn = np.dot(s, g + 0.5*Hs)
|
|
86
|
+
if h is not None:
|
|
87
|
+
hvalue = h(remove_scaling(xopt+s, scaling_changes), *argsh)
|
|
88
|
+
rtn += hvalue
|
|
89
|
+
return rtn
|
|
76
90
|
|
|
77
91
|
|
|
78
92
|
def get_scale(dirn, delta, lower, upper):
|
|
@@ -207,3 +221,50 @@ def remove_scaling(x_scaled, scaling_changes):
|
|
|
207
221
|
shift, scale = scaling_changes
|
|
208
222
|
return shift + x_scaled * scale
|
|
209
223
|
|
|
224
|
+
|
|
225
|
+
def dykstra(P,x0,max_iter=100,tol=1e-10):
|
|
226
|
+
x = x0.copy()
|
|
227
|
+
p = len(P)
|
|
228
|
+
y = np.zeros((p,x0.shape[0]))
|
|
229
|
+
|
|
230
|
+
n = 0
|
|
231
|
+
cI = float('inf')
|
|
232
|
+
while n < max_iter and cI >= tol:
|
|
233
|
+
cI = 0
|
|
234
|
+
for i in range(0,p):
|
|
235
|
+
# Update iterate
|
|
236
|
+
prev_x = x.copy()
|
|
237
|
+
x = P[i](prev_x - y[i,:])
|
|
238
|
+
|
|
239
|
+
# Update increment
|
|
240
|
+
prev_y = y[i,:].copy()
|
|
241
|
+
y[i,:] = x - (prev_x - prev_y)
|
|
242
|
+
|
|
243
|
+
# Stop condition
|
|
244
|
+
cI += np.linalg.norm(prev_y - y[i,:])**2
|
|
245
|
+
|
|
246
|
+
n += 1
|
|
247
|
+
|
|
248
|
+
return x
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
def pball(x,c,r):
|
|
252
|
+
return c + (r/np.max([np.linalg.norm(x-c),r]))*(x-c)
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
def pbox(x,l,u):
|
|
256
|
+
return np.minimum(np.maximum(x,l), u)
|
|
257
|
+
|
|
258
|
+
'''
|
|
259
|
+
Calculates rank of square matrix with QR.
|
|
260
|
+
We use the fact that the rank of a square matrix A
|
|
261
|
+
can be given by the number of nonzero diagonal elements of
|
|
262
|
+
R in the QR factorization of A.
|
|
263
|
+
'''
|
|
264
|
+
def qr_rank(A,tol=1e-15):
|
|
265
|
+
m,n = A.shape
|
|
266
|
+
assert m == n, "Input matrix must be square"
|
|
267
|
+
Q,R = LA.qr(A)
|
|
268
|
+
D = np.abs(np.diag(R))
|
|
269
|
+
rank = np.sum(D > tol)
|
|
270
|
+
return rank, D
|
DFO_LS-1.2.1.dist-info/RECORD
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
dfols/__init__.py,sha256=WdWULFDmitwdbZ3JEcrbkb5DjXr0ZM6efAqSe-iPsr8,1620
|
|
2
|
-
dfols/controller.py,sha256=7puR1_zuu47Vr-xEhqubEJRzLv2Yja3X2O_WeDaDSV0,35652
|
|
3
|
-
dfols/diagnostic_info.py,sha256=2kEUkL-MS4eDENUf1r2hOWsntP8OxMDKi_kyHmrC9V4,6081
|
|
4
|
-
dfols/hessian.py,sha256=DKOm520rrFFaXVXu-BsD7aj2_ilJohxZ2tnMsnSa8zE,4265
|
|
5
|
-
dfols/model.py,sha256=OHi-Y50OajpIauzfGcYPdCSrM8gvXYTGjb3NY7enk9s,18020
|
|
6
|
-
dfols/params.py,sha256=1Mplj96q9anYa6d3PCkXgsxp-tc9fP4mNtQxwm7bveE,16749
|
|
7
|
-
dfols/solver.py,sha256=RPUQpgPRkcUVMvc6tJ-0bYckg8EesMMeQ1meRJk3u_k,59180
|
|
8
|
-
dfols/trust_region.py,sha256=75Z0z2d6ENh8t9t_e95IVwgNaWlZpyZF4rdkMJ54qhc,19152
|
|
9
|
-
dfols/util.py,sha256=gpDa71PSFhFMqIJdmndnJ0vE25BiSulscRPS6MlIyaE,8667
|
|
10
|
-
dfols/version.py,sha256=GQUgqQ6kgZyC6ohszFAofexRKp-dKwWY81bo7q2hlI8,926
|
|
11
|
-
DFO_LS-1.2.1.dist-info/LICENSE.txt,sha256=jOtLnuWt7d5Hsx6XXB2QxzrSe2sWWh3NgMfFRetluQM,35147
|
|
12
|
-
DFO_LS-1.2.1.dist-info/METADATA,sha256=nyESs24W-UXP0yYFZ8XX7YGOv39pIPKc8UAvRHrLfEc,7039
|
|
13
|
-
DFO_LS-1.2.1.dist-info/WHEEL,sha256=g4nMs7d-Xl9-xC9XovUrsDHGXt-FT0E17Yqo92DEfvY,92
|
|
14
|
-
DFO_LS-1.2.1.dist-info/top_level.txt,sha256=UfxRhaDN8HQx2_l17KbrDrERJ90OCN7VKkDMpYYbRLU,6
|
|
15
|
-
DFO_LS-1.2.1.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
16
|
-
DFO_LS-1.2.1.dist-info/RECORD,,
|
DFO_LS-1.2.1.dist-info/zip-safe
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
|
dfols/version.py
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Version number
|
|
3
|
-
====
|
|
4
|
-
|
|
5
|
-
This program is free software: you can redistribute it and/or modify
|
|
6
|
-
it under the terms of the GNU General Public License as published by
|
|
7
|
-
the Free Software Foundation, either version 3 of the License, or
|
|
8
|
-
(at your option) any later version.
|
|
9
|
-
|
|
10
|
-
This program is distributed in the hope that it will be useful,
|
|
11
|
-
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
-
GNU General Public License for more details.
|
|
14
|
-
|
|
15
|
-
You should have received a copy of the GNU General Public License
|
|
16
|
-
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
17
|
-
|
|
18
|
-
The development of this software was sponsored by NAG Ltd. (http://www.nag.co.uk)
|
|
19
|
-
and the EPSRC Centre For Doctoral Training in Industrially Focused Mathematical
|
|
20
|
-
Modelling (EP/L015803/1) at the University of Oxford. Please contact NAG for
|
|
21
|
-
alternative licensing.
|
|
22
|
-
|
|
23
|
-
"""
|
|
24
|
-
|
|
25
|
-
__version__ = '1.2.1'
|
|
File without changes
|