Skip to content

Commit 58104c7

Browse files
committed
Add more util tests and remove more pdb
1 parent 3ba2e3f commit 58104c7

File tree

3 files changed

+135
-7
lines changed

3 files changed

+135
-7
lines changed

dfols/params.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ def __init__(self, n, npt, maxfun, objfun_has_noise=False):
113113
self.params["dykstra.d_tol"] = 1e-10
114114
self.params["dykstra.max_iters"] = 100
115115
# Matrix rank algorithm
116-
self.params["matrix_rank.r_tol"] = 1e-16
116+
self.params["matrix_rank.r_tol"] = 1e-15
117117

118118
self.params_changed = {}
119119
for p in self.params:

dfols/tests/test_util.py

Lines changed: 132 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,4 +165,135 @@ def runTest(self):
165165
self.assertTrue(np.linalg.norm(dirns[i, :]) <= delta + 1e-10, "Unconstrained: dirn %i too long" % i)
166166
self.assertTrue(np.all(dirns[i, :] >= lower), "Direction %i below lower bound" % i)
167167
self.assertTrue(np.all(dirns[i, :] <= upper), "Direction %i above upper bound" % i)
168-
# self.assertTrue(False, "bad")
168+
# self.assertTrue(False, "bad")
169+
170+
# Trivial case of full rank
171+
class TestMatrixRankQR1(unittest.TestCase):
172+
def runTest(self):
173+
mr_tol = 1e-15
174+
A = np.array([
175+
[1,0,0,0],
176+
[0,1,0,0],
177+
[0,0,1,0],
178+
[0,0,0,1]])
179+
rank, D = qr_rank(A,mr_tol)
180+
self.assertTrue(np.all(D > mr_tol), "Incorrect diagonal matrix output")
181+
self.assertTrue(rank == 4, "Incorrect rank output")
182+
183+
# Full rank but QR has negative entries for diag(R)
184+
class TestMatrixRankQR2(unittest.TestCase):
185+
def runTest(self):
186+
mr_tol = 1e-15
187+
A = np.array([
188+
[1,2,3,4],
189+
[0,6,7,8],
190+
[-1,-2,-2,-1],
191+
[4,2,2,1]])
192+
rank, D = qr_rank(A,mr_tol)
193+
self.assertTrue(np.all(D > mr_tol), "Incorrect diagonal matrix output")
194+
self.assertTrue(rank == 4, "Incorrect rank output")
195+
196+
197+
# Full rank but QR has negative entries for diag(R)
198+
class TestMatrixRankQR3(unittest.TestCase):
199+
def runTest(self):
200+
mr_tol = 1e-15
201+
A = np.array([
202+
[1,2,3,4],
203+
[2,6,4,8],
204+
[-1,-2,-3,-4],
205+
[1,3,2,4]])
206+
rank, D = qr_rank(A,mr_tol)
207+
self.assertTrue(np.all(D[0:2] > mr_tol), "Incorrect diagonal matrix output (rows 1,2)")
208+
self.assertTrue(np.all(D[2:4] <= mr_tol), "Incorrect diagonal matrix output (rows 3,4)")
209+
self.assertTrue(rank == 2, "Incorrect rank output")
210+
211+
212+
class TestDykstraBoxInt(unittest.TestCase):
213+
def runTest(self):
214+
x0 = np.array([0,0])
215+
lower = np.array([-0.01, -0.1])
216+
upper = np.array([0.01, 0.5])
217+
boxproj = lambda x: pbox(x,lower,upper)
218+
P = [boxproj]
219+
xproj = dykstra(P,x0)
220+
self.assertTrue(np.all(xproj == x0), "Incorrect point returned by Dykstra")
221+
222+
223+
class TestDykstraBoxExt(unittest.TestCase):
224+
def runTest(self):
225+
x0 = np.array([-2,5])
226+
lower = np.array([-1, -1])
227+
upper = np.array([0.5, 0.9])
228+
boxproj = lambda x: pbox(x,lower,upper)
229+
P = [boxproj]
230+
xproj = dykstra(P,x0)
231+
xtrue = np.array([-1,0.9])
232+
self.assertTrue(np.allclose(xproj, xtrue), "Incorrect point returned by Dykstra")
233+
234+
class TestDykstraBallInt(unittest.TestCase):
235+
def runTest(self):
236+
x0 = np.array([0,0])
237+
ballproj = lambda x: pball(x,x0+1,2)
238+
P = [ballproj]
239+
xproj = dykstra(P,x0)
240+
self.assertTrue(np.all(xproj == x0), "Incorrect point returned by Dykstra")
241+
242+
243+
class TestDykstraBallExt(unittest.TestCase):
244+
def runTest(self):
245+
x0 = np.array([-3,5])
246+
ballproj = lambda x: pball(x,np.array([-0.5,1]),1)
247+
P = [ballproj]
248+
xproj = dykstra(P,x0)
249+
xtrue = np.array([-1.02999894, 1.8479983])
250+
self.assertTrue(np.allclose(xproj, xtrue), "Incorrect point returned by Dykstra")
251+
252+
253+
class TestDykstraBoxBallInt(unittest.TestCase):
254+
def runTest(self):
255+
x0 = np.array([0.72,1.1])
256+
lower = np.array([0.7, -2.0])
257+
upper = np.array([1.0, 2])
258+
boxproj = lambda x: pbox(x,lower,upper)
259+
ballproj = lambda x: pball(x,np.array([0.5,1]),0.25)
260+
P = [boxproj,ballproj]
261+
xproj = dykstra(P,x0)
262+
self.assertTrue(np.all(xproj == x0), "Incorrect point returned by Dykstra")
263+
264+
class TestDykstraBoxBallExt1(unittest.TestCase):
265+
def runTest(self):
266+
x0 = np.array([0,4])
267+
lower = np.array([0.7, -2.0])
268+
upper = np.array([1.0, 2])
269+
boxproj = lambda x: pbox(x,lower,upper)
270+
ballproj = lambda x: pball(x,np.array([0.5,1]),0.25)
271+
P = [boxproj,ballproj]
272+
xproj = dykstra(P,x0)
273+
xtrue = np.array([0.6940582, 1.1576116])
274+
self.assertTrue(np.allclose(xproj, xtrue), "Incorrect point returned by Dykstra")
275+
276+
277+
class TestDykstraBoxBallExt2(unittest.TestCase):
278+
def runTest(self):
279+
x0 = np.array([0.8,-3])
280+
lower = np.array([0.7, -2.0])
281+
upper = np.array([1.0, 2])
282+
boxproj = lambda x: pbox(x,lower,upper)
283+
ballproj = lambda x: pball(x,np.array([0.5,1]),0.25)
284+
P = [boxproj,ballproj]
285+
xproj = dykstra(P,x0)
286+
xtrue = np.array([0.68976232, 0.8372417])
287+
self.assertTrue(np.allclose(xproj, xtrue), "Incorrect point returned by Dykstra")
288+
289+
290+
class TestDykstraBoxBallBdry(unittest.TestCase):
291+
def runTest(self):
292+
x0 = np.array([0.7,0.85])
293+
lower = np.array([0.7, -2.0])
294+
upper = np.array([1.0, 2])
295+
boxproj = lambda x: pbox(x,lower,upper)
296+
ballproj = lambda x: pball(x,np.array([0.5,1]),0.25)
297+
P = [boxproj,ballproj]
298+
xproj = dykstra(P,x0)
299+
self.assertTrue(np.allclose(xproj, x0), "Incorrect point returned by Dykstra")

dfols/util.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,6 @@
3030
import scipy.linalg as LA
3131
import sys
3232

33-
import pdb
34-
3533

3634
__all__ = ['sumsq', 'eval_least_squares_objective', 'model_value', 'random_orthog_directions_within_bounds',
3735
'random_directions_within_bounds', 'apply_scaling', 'remove_scaling', 'pbox', 'pball', 'dykstra', 'qr_rank']
@@ -211,7 +209,7 @@ def remove_scaling(x_scaled, scaling_changes):
211209
return shift + x_scaled * scale
212210

213211

214-
def dykstra(P,x0,max_iter=100,tol=1.0e-10):
212+
def dykstra(P,x0,max_iter=100,tol=1e-10):
215213
x = x0.copy()
216214
p = len(P)
217215
y = np.zeros((p,x0.shape[0]))
@@ -226,7 +224,6 @@ def dykstra(P,x0,max_iter=100,tol=1.0e-10):
226224
x = P[i](prev_x - y[i,:])
227225

228226
# Update increment
229-
# pdb.set_trace()
230227
prev_y = y[i,:].copy()
231228
y[i,:] = x - (prev_x - prev_y)
232229

@@ -251,7 +248,7 @@ def pbox(x,l,u):
251248
can be given by the number of nonzero diagonal elements of
252249
R in the QR factorization of A.
253250
'''
254-
def qr_rank(A,tol=1e-25):
251+
def qr_rank(A,tol=1e-15):
255252
m,n = A.shape
256253
assert m == n, "Input matrix must be square"
257254
Q,R = LA.qr(A)

0 commit comments

Comments
 (0)