Skip to content

Commit 0990ef7

Browse files
committed
Add tests for TR subproblem. Make curvature calc more robust.
1 parent d32b952 commit 0990ef7

File tree

2 files changed

+112
-244
lines changed

2 files changed

+112
-244
lines changed

dfols/tests/test_trust_region.py

Lines changed: 111 additions & 243 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
from dfols.trust_region import ctrsbox, ctrsbox_geometry, trsbox, trsbox_geometry
3131
from dfols.util import model_value
3232

33+
import pdb
34+
3335

3436
def cauchy_pt(g, H, delta):
3537
# General expression for the Cauchy point
@@ -73,167 +75,8 @@ def cauchy_pt_box(g, H, delta, lower, upper):
7375
def p_box(x,l,u):
7476
return np.minimum(np.maximum(x,l), u)
7577

76-
class TestUncInternalCDFO(unittest.TestCase):
77-
def runTest(self):
78-
n = 3
79-
g = np.array([1.0, 0.0, 1.0])
80-
H = np.array([[1.0, 0.0, 0.0], [0.0, 2.0, 0.0], [0.0, 0.0, 2.0]])
81-
Delta = 2.0
82-
xopt = np.ones((n,)) # trying nonzero (since bounds inactive)
83-
sl = -1e20 * np.ones((n,))
84-
su = 1e20 * np.ones((n,))
85-
d, gnew, crvmin = ctrsbox(xopt, g, H, sl, su, [], Delta)
86-
true_d = np.array([-1.0, 0.0, -0.5])
87-
est_min = model_value(g, H, d)
88-
true_min = model_value(g, H, true_d)
89-
# Hope to get actual correct answer for internal minimum?
90-
# self.assertTrue(np.all(d == true_d), 'Wrong answer')
91-
# self.assertAlmostEqual(est_min, true_min, 'Wrong min value')
92-
s_cauchy, red_cauchy, crvmin_cauchy = cauchy_pt(g, H, Delta)
93-
self.assertTrue(est_min <= red_cauchy, 'Cauchy reduction not achieved')
94-
self.assertTrue(np.all(gnew == g + H.dot(d)), 'Wrong gnew')
95-
print(crvmin)
96-
self.assertAlmostEqual(crvmin, 1.2, 'Wrong crvmin')
97-
98-
class TestUncBdryCDFO(unittest.TestCase):
99-
def runTest(self):
100-
n = 3
101-
g = np.array([1.0, 0.0, 1.0])
102-
H = np.array([[1.0, 0.0, 0.0], [0.0, 2.0, 0.0], [0.0, 0.0, 2.0]])
103-
Delta = 5.0 / 12.0
104-
xopt = np.zeros((n,))
105-
sl = -1e20 * np.ones((n,))
106-
su = 1e20 * np.ones((n,))
107-
pbox = lambda x: p_box(x,sl,su)
108-
d, gnew, crvmin = ctrsbox(xopt, g, H, sl, su, [], Delta)
109-
true_d = np.array([-1.0 / 3.0, 0.0, -0.25])
110-
est_min = model_value(g, H, d)
111-
true_min = model_value(g, H, true_d)
112-
# Hope to get actual correct answer
113-
# self.assertTrue(np.all(d == true_d), 'Wrong answer')
114-
# self.assertAlmostEqual(est_min, true_min, 'Wrong min value')
115-
s_cauchy, red_cauchy, crvmin_cauchy = cauchy_pt(g, H, Delta)
116-
self.assertTrue(est_min <= red_cauchy, 'Cauchy reduction not achieved')
117-
self.assertTrue(np.all(gnew == g + H.dot(d)), 'Wrong gnew')
118-
self.assertAlmostEqual(crvmin, 0.0, 'Wrong crvmin')
119-
120-
class TestUncBdry2CDFO(unittest.TestCase):
121-
def runTest(self):
122-
n = 3
123-
g = np.array([1.0, 0.0, 1.0])
124-
H = np.array([[-2.0, 0.0, 0.0], [0.0, -1.0, 0.0], [0.0, 0.0, -1.0]])
125-
Delta = 5.0 / 12.0
126-
xopt = np.zeros((n,))
127-
sl = -1e20 * np.ones((n,))
128-
su = 1e20 * np.ones((n,))
129-
pbox = lambda x: p_box(x,sl,su)
130-
d, gnew, crvmin = ctrsbox(xopt, g, H, sl, su, [], Delta)
131-
true_d = np.array([-1.0 / 3.0, 0.0, -0.25])
132-
est_min = model_value(g, H, d)
133-
true_min = model_value(g, H, true_d)
134-
# Hope to get actual correct answer
135-
# self.assertTrue(np.all(d == true_d), 'Wrong answer')
136-
# self.assertAlmostEqual(est_min, true_min, 'Wrong min value')
137-
s_cauchy, red_cauchy, crvmin_cauchy = cauchy_pt(g, H, Delta)
138-
self.assertTrue(est_min <= red_cauchy, 'Cauchy reduction not achieved')
139-
self.assertTrue(np.allclose(gnew, g + H.dot(d)), 'Wrong gnew')
140-
self.assertAlmostEqual(crvmin, 0.0, 'Wrong crvmin')
141-
142-
class TestUncBdry3CDFO(unittest.TestCase):
143-
def runTest(self):
144-
n = 3
145-
g = np.array([0.0, 0.0, 1.0])
146-
H = np.array([[-2.0, 0.0, 0.0], [0.0, -1.0, 0.0], [0.0, 0.0, -1.0]])
147-
Delta = 0.5
148-
xopt = np.zeros((n,))
149-
sl = -1e20 * np.ones((n,))
150-
su = 1e20 * np.ones((n,))
151-
pbox = lambda x: p_box(x,sl,su)
152-
d, gnew, crvmin = ctrsbox(xopt, g, H, sl, su, [], Delta)
153-
true_d = np.array([0.0, 0.0, -0.5])
154-
est_min = model_value(g, H, d)
155-
true_min = model_value(g, H, true_d)
156-
# Hope to get actual correct answer
157-
# self.assertTrue(np.all(d == true_d), 'Wrong answer')
158-
# self.assertAlmostEqual(est_min, true_min, 'Wrong min value')
159-
s_cauchy, red_cauchy, crvmin_cauchy = cauchy_pt(g, H, Delta)
160-
self.assertTrue(est_min <= red_cauchy, 'Cauchy reduction not achieved')
161-
self.assertTrue(np.all(gnew == g + H.dot(d)), 'Wrong gnew')
162-
self.assertAlmostEqual(crvmin, 0.0, 'Wrong crvmin')
163-
# self.assertAlmostEqual(crvmin, crvmin_cauchy, 'Wrong crvmin')
164-
165-
class TestUncHardCDFO(unittest.TestCase):
166-
def runTest(self):
167-
n = 3
168-
g = np.array([0.0, 0.0, 1.0])
169-
H = np.array([[-2.0, 0.0, 0.0], [0.0, -1.0, 0.0], [0.0, 0.0, -1.0]])
170-
Delta = sqrt(2.0)
171-
xopt = np.zeros((n,))
172-
sl = -1e20 * np.ones((n,))
173-
su = 1e20 * np.ones((n,))
174-
pbox = lambda x: p_box(x,sl,su)
175-
d, gnew, crvmin = ctrsbox(xopt, g, H, sl, su, [], Delta)
176-
true_d = np.array([1.0, 0.0, -1.0]) # non-unique solution
177-
est_min = model_value(g, H, d)
178-
true_min = model_value(g, H, true_d)
179-
# Hope to get actual correct answer
180-
# self.assertTrue(np.all(d == true_d), 'Wrong answer')
181-
# self.assertAlmostEqual(est_min, true_min, 'Wrong min value')
182-
s_cauchy, red_cauchy, crvmin_cauchy = cauchy_pt(g, H, Delta)
183-
self.assertTrue(est_min <= red_cauchy, 'Cauchy reduction not achieved')
184-
self.assertTrue(np.all(gnew == g + H.dot(d)), 'Wrong gnew')
185-
self.assertAlmostEqual(crvmin, 0.0, 'Wrong crvmin')
186-
187-
class TestConInternalCDFO(unittest.TestCase):
188-
def runTest(self):
189-
n = 3
190-
g = np.array([1.0, 0.0, 1.0])
191-
H = np.array([[1.0, 0.0, 0.0], [0.0, 2.0, 0.0], [0.0, 0.0, 2.0]])
192-
Delta = 2.0
193-
xopt = np.ones((n,)) # trying nonzero (since bounds inactive)
194-
sl = xopt + np.array([-0.5, -10.0, -10.0])
195-
su = xopt + np.array([10.0, 10.0, 10.0])
196-
pbox = lambda x: p_box(x,sl,su)
197-
d, gnew, crvmin = ctrsbox(xopt, g, H, sl, su, [], Delta)
198-
true_d = np.array([-1.0, 0.0, -0.5])
199-
est_min = model_value(g, H, d)
200-
true_min = model_value(g, H, true_d)
201-
# Hope to get actual correct answer for internal minimum?
202-
# self.assertTrue(np.all(d == true_d), 'Wrong answer')
203-
# self.assertAlmostEqual(est_min, true_min, 'Wrong min value')
204-
s_cauchy, red_cauchy, crvmin_cauchy = cauchy_pt_box(g, H, Delta, sl-xopt, su-xopt)
205-
# print(s_cauchy)
206-
# print(d)
207-
self.assertTrue(est_min <= red_cauchy, 'Cauchy reduction not achieved')
208-
self.assertTrue(np.all(gnew == g + H.dot(d)), 'Wrong gnew')
209-
print(crvmin)
210-
self.assertAlmostEqual(crvmin, -1.0, 'Wrong crvmin')
211-
212-
213-
# Notes: Gets correct min and gnew. Incorrect crvmin (1.0999999999999999).
214-
class TestConBdryCDFO(unittest.TestCase):
215-
def runTest(self):
216-
n = 3
217-
g = np.array([1.0, 0.0, 1.0])
218-
H = np.array([[1.0, 0.0, 0.0], [0.0, 2.0, 0.0], [0.0, 0.0, 2.0]])
219-
Delta = 5.0 / 12.0
220-
xopt = np.zeros((n,))
221-
sl = xopt + np.array([-0.3, -0.01, -0.1])
222-
su = xopt + np.array([10.0, 1.0, 10.0])
223-
pbox = lambda x: p_box(x,sl,su)
224-
d, gnew, crvmin = ctrsbox(xopt, g, H, sl, su, [], Delta)
225-
true_d = np.array([-1.0 / 3.0, 0.0, -0.25])
226-
est_min = model_value(g, H, d)
227-
true_min = model_value(g, H, true_d)
228-
# Hope to get actual correct answer
229-
# self.assertTrue(np.all(d == true_d), 'Wrong answer')
230-
# self.assertAlmostEqual(est_min, true_min, 'Wrong min value')
231-
s_cauchy, red_cauchy, crvmin_cauchy = cauchy_pt_box(g, H, Delta, sl - xopt, su - xopt)
232-
self.assertTrue(est_min <= red_cauchy, 'Cauchy reduction not achieved')
233-
self.assertTrue(np.max(np.abs(gnew - g - H.dot(d))) < 1e-10, 'Wrong gnew')
234-
print(crvmin)
235-
self.assertAlmostEqual(crvmin, -1.0, 'Wrong crvmin')
236-
# self.assertAlmostEqual(crvmin, crvmin_cauchy, 'Wrong crvmin')
78+
def p_ball(x,c,r):
79+
return c + (r/np.max([np.linalg.norm(x-c),r]))*(x-c)
23780

23881

23982
class TestUncInternal(unittest.TestCase):
@@ -507,108 +350,133 @@ def runTest(self):
507350
self.assertTrue(np.max(np.abs(x - xtrue)) < 1e-10, 'Wrong step')
508351

509352

510-
class TestGeomCDFO(unittest.TestCase):
511-
def runTest(self):
512-
xbase = np.array([0.0, 0.0])
513-
g = np.array([1.0, -1.0])
514-
a = np.array([-2.0, -2.0])
515-
b = np.array([1.0, 2.0])
516-
delta = 2.0
517-
c = -1.0
518-
x = ctrsbox_geometry(xbase, c, g, a, b, [], delta)
519-
xtrue = np.array([-sqrt(2.0), sqrt(2.0)])
520-
self.assertTrue(np.max(np.abs(x - xtrue)) < 1e-10, 'Wrong step')
521-
522-
523-
class TestGeom2CDFO(unittest.TestCase):
524-
def runTest(self):
525-
xbase = np.array([0.0, 0.0])
526-
g = np.array([1.0, -1.0])
527-
a = np.array([-2.0, -2.0])
528-
b = np.array([1.0, 2.0])
529-
delta = 5.0
530-
c = -1.0
531-
x = ctrsbox_geometry(xbase, c, g, a, b, [], delta)
532-
xtrue = np.array([-2.0, 2.0])
533-
self.assertTrue(np.max(np.abs(x - xtrue)) < 1e-10, 'Wrong step')
534-
535-
353+
# DFO-LS with arbitrary constraints
536354
class TestGeom3CDFO(unittest.TestCase):
537355
def runTest(self):
538356
xbase = np.array([0.0, 0.0]) + 1
539357
g = np.array([1.0, -1.0])
540358
a = np.array([-2.0, -2.0]) + 1
541359
b = np.array([1.0, 2.0]) + 1
360+
proj = lambda x: p_box(x,a,b)
542361
delta = 5.0
543362
c = 3.0 # may want to max instead
544-
x = ctrsbox_geometry(xbase, c, g, a, b, [], delta)
545-
xtrue = np.array([1.0, -2.0]) + 1
363+
x = ctrsbox_geometry(xbase, c, g, [proj], delta)
364+
xtrue = np.array([1.0, -2.0])
546365
self.assertTrue(np.max(np.abs(x - xtrue)) < 1e-10, 'Wrong step')
547366

367+
class TestUncInternalCDFO(unittest.TestCase):
368+
def runTest(self):
369+
n = 3
370+
g = np.array([1.0, 0.0, 1.0])
371+
H = np.array([[1.0, 0.0, 0.0], [0.0, 2.0, 0.0], [0.0, 0.0, 2.0]])
372+
Delta = 2.0
373+
xopt = np.ones((n,)) # trying nonzero (since bounds inactive)
374+
d, gnew, _crvmin = ctrsbox(xopt, g, H, [], Delta)
375+
true_d = np.array([-1.0, 0.0, -0.5])
376+
est_min = model_value(g, H, d)
377+
true_min = model_value(g, H, true_d)
378+
s_cauchy, red_cauchy, _crvmin_cauchy = cauchy_pt(g, H, Delta)
379+
self.assertTrue(est_min <= red_cauchy, 'Cauchy reduction not achieved')
380+
self.assertTrue(np.all(gnew == g + H.dot(d)), 'Wrong gnew')
548381

549-
class TestGeomOldBugCDFO(unittest.TestCase):
382+
class TestUncBdryCDFO(unittest.TestCase):
550383
def runTest(self):
551-
xbase = np.array([0.0, 0.0])
552-
g = np.array([-1.0, -1.0])
553-
a = np.array([-2.0, -2.0])
554-
b = np.array([0.1, 0.9])
555-
delta = sqrt(2.0)
556-
c = -1.0 # may want to max instead
557-
x = ctrsbox_geometry(xbase, c, g, a, b, [], delta)
558-
xtrue = b
559-
self.assertTrue(np.max(np.abs(x - xtrue)) < 1e-10, 'Wrong step')
560-
# self.assertFalse(True, "bad")
384+
n = 3
385+
g = np.array([1.0, 0.0, 1.0])
386+
H = np.array([[1.0, 0.0, 0.0], [0.0, 2.0, 0.0], [0.0, 0.0, 2.0]])
387+
Delta = 5.0 / 12.0
388+
xopt = np.zeros((n,))
389+
d, gnew, _crvmin = ctrsbox(xopt, g, H, [], Delta)
390+
true_d = np.array([-1.0 / 3.0, 0.0, -0.25])
391+
est_min = model_value(g, H, d)
392+
true_min = model_value(g, H, true_d)
393+
s_cauchy, red_cauchy, _crvmin_cauchy = cauchy_pt(g, H, Delta)
394+
self.assertTrue(est_min <= red_cauchy, 'Cauchy reduction not achieved')
395+
self.assertTrue(np.allclose(gnew, g + H.dot(d)), 'Wrong gnew')
561396

562397

563-
class TestGeomOldBug2CDFO(unittest.TestCase):
398+
class TestUncHardCDFO(unittest.TestCase):
564399
def runTest(self):
565-
xbase = np.array([0.0, 0.0, 0.0])
566-
g = np.array([-1.0, -1.0, -1.0])
567-
a = np.array([-2.0, -2.0, -2.0])
568-
b = np.array([0.9, 0.1, 5.0])
569-
delta = sqrt(3.0)
570-
c = -1.0 # may want to max instead
571-
x = ctrsbox_geometry(xbase, c, g, a, b, [], delta)
572-
xtrue = np.array([0.9, 0.1, sqrt(3.0 - 0.81 - 0.01)])
573-
self.assertTrue(np.max(np.abs(x - xtrue)) < 1e-10, 'Wrong step')
574-
# self.assertFalse(True, "bad")
400+
n = 3
401+
g = np.array([0.0, 0.0, 1.0])
402+
H = np.array([[-2.0, 0.0, 0.0], [0.0, -1.0, 0.0], [0.0, 0.0, -1.0]])
403+
Delta = sqrt(2.0)
404+
xopt = np.zeros((n,))
405+
d, gnew, _crvmin = ctrsbox(xopt, g, H, [], Delta)
406+
true_d = np.array([1.0, 0.0, -1.0]) # non-unique solution
407+
est_min = model_value(g, H, d)
408+
true_min = model_value(g, H, true_d)
409+
s_cauchy, red_cauchy, _crvmin_cauchy = cauchy_pt(g, H, Delta)
410+
self.assertTrue(est_min <= red_cauchy, 'Cauchy reduction not achieved')
411+
self.assertTrue(np.allclose(gnew, g + H.dot(d)), 'Wrong gnew')
575412

576-
class TestGeom2WithZerosCDFO(unittest.TestCase):
413+
class TestConInternalCDFO(unittest.TestCase):
577414
def runTest(self):
578-
xbase = np.array([0.0, 0.0])
579-
g = np.array([0.0, -1.0])
580-
a = np.array([-2.0, -2.0])
581-
b = np.array([1.0, 2.0])
582-
delta = 5.0
583-
c = 0.0
584-
x = ctrsbox_geometry(xbase, c, g, a, b, [], delta)
585-
xtrue = np.array([0.0, 2.0])
586-
self.assertTrue(np.max(np.abs(x - xtrue)) < 1e-10, 'Wrong step')
415+
n = 3
416+
g = np.array([1.0, 0.0, 1.0])
417+
H = np.array([[1.0, 0.0, 0.0], [0.0, 2.0, 0.0], [0.0, 0.0, 2.0]])
418+
Delta = 2.0
419+
xopt = np.ones((n,)) # trying nonzero (since bounds inactive)
420+
sl = xopt + np.array([-0.5, -10.0, -10.0])
421+
su = xopt + np.array([10.0, 10.0, 10.0])
422+
proj = lambda x: p_box(x,sl,su)
423+
d, gnew, _crvmin = ctrsbox(xopt, g, H, [proj], Delta)
424+
true_d = np.array([-1.0, 0.0, -0.5])
425+
est_min = model_value(g, H, d)
426+
true_min = model_value(g, H, true_d)
427+
s_cauchy, red_cauchy, _crvmin_cauchy = cauchy_pt_box(g, H, Delta, sl-xopt, su-xopt)
428+
self.assertTrue(est_min <= red_cauchy, 'Cauchy reduction not achieved')
429+
self.assertTrue(np.all(gnew == g + H.dot(d)), 'Wrong gnew')
587430

431+
class TestConBdryCDFO(unittest.TestCase):
432+
def runTest(self):
433+
n = 3
434+
g = np.array([1.0, 0.0, 1.0])
435+
H = np.array([[1.0, 0.0, 0.0], [0.0, 2.0, 0.0], [0.0, 0.0, 2.0]])
436+
Delta = 5.0 / 12.0
437+
xopt = np.zeros((n,))
438+
sl = xopt + np.array([-0.3, -0.01, -0.1])
439+
su = xopt + np.array([10.0, 1.0, 10.0])
440+
proj = lambda x: p_box(x,sl,su)
441+
d, gnew, _crvmin = ctrsbox(xopt, g, H, [proj], Delta)
442+
true_d = np.array([-1.0 / 3.0, 0.0, -0.25])
443+
est_min = model_value(g, H, d)
444+
true_min = model_value(g, H, true_d)
445+
s_cauchy, red_cauchy, _crvmin_cauchy = cauchy_pt_box(g, H, Delta, sl - xopt, su - xopt)
446+
self.assertTrue(est_min <= red_cauchy, 'Cauchy reduction not achieved')
447+
self.assertTrue(np.max(np.abs(gnew - g - H.dot(d))) < 1e-10, 'Wrong gnew')
588448

589-
class TestGeom2WithAlmostZerosCDFO(unittest.TestCase):
449+
class TestBoxBallInternalCDFO(unittest.TestCase):
590450
def runTest(self):
591-
xbase = np.array([0.0, 0.0])
592-
g = np.array([1e-15, -1.0])
593-
a = np.array([-2.0, -2.0])
594-
b = np.array([1.0, 2.0])
595-
delta = 5.0
596-
c = 0.0
597-
x = ctrsbox_geometry(xbase, c, g, a, b, [], delta)
598-
xtrue = np.array([0.0, 2.0])
599-
self.assertTrue(np.max(np.abs(x - xtrue)) < 1e-10, 'Wrong step')
451+
n = 3
452+
g = np.array([1.0, 0.0, 1.0])
453+
H = np.array([[1.0, 0.0, 0.0], [0.0, 2.0, 0.0], [0.0, 0.0, 2.0]])
454+
Delta = 2.0
455+
xopt = np.ones((n,)) # trying nonzero (since bounds inactive)
456+
sl = xopt + np.array([-0.5, -10.0, -10.0])
457+
su = xopt + np.array([10.0, 10.0, 10.0])
458+
boxproj = lambda x: p_box(x,sl,su)
459+
ballproj = lambda x: p_ball(x,xopt,5)
460+
d, gnew, _crvmin = ctrsbox(xopt, g, H, [boxproj,ballproj], Delta)
461+
true_d = np.array([-0.5, 0.0, -0.5])
462+
est_min = model_value(g, H, d)
463+
true_min = model_value(g, H, true_d)
464+
self.assertTrue(est_min <= true_min + 1e-3, 'Sufficient decrease not achieved')
600465

601466

602-
class TestGeom2WithAlmostZeros2CDFO(unittest.TestCase):
467+
class TestBoxBallBdryCDFO(unittest.TestCase):
603468
def runTest(self):
604-
xbase = np.array([0.0, 0.0])
605-
g = np.array([1e-15, 0.0])
606-
a = np.array([-2.0, -2.0])
607-
b = np.array([1.0, 2.0])
608-
delta = 5.0
609-
c = 0.0
610-
x = ctrsbox_geometry(xbase, c, g, a, b, [], delta)
611-
xtrue = np.array([0.0, 0.0])
612-
# print(x)
613-
# print(xtrue)
614-
self.assertTrue(np.max(np.abs(x - xtrue)) < 1e-10, 'Wrong step')
469+
n = 3
470+
g = np.array([1.0, 0.0, 1.0])
471+
H = np.array([[1.0, 0.0, 0.0], [0.0, 2.0, 0.0], [0.0, 0.0, 2.0]])
472+
Delta = 5.0 / 12.0
473+
xopt = np.zeros((n,))
474+
sl = xopt + np.array([-0.3, -0.01, -0.1])
475+
su = xopt + np.array([10.0, 1.0, 10.0])
476+
boxproj = lambda x: p_box(x,sl,su)
477+
ballproj = lambda x: p_ball(x,xopt,0.25)
478+
d, gnew, _crvmin = ctrsbox(xopt, g, H, [boxproj,ballproj], Delta)
479+
true_d = np.array([-0.22913085, 0.0, -0.09999527])
480+
est_min = model_value(g, H, d)
481+
true_min = model_value(g, H, true_d)
482+
self.assertTrue(est_min <= true_min + 1e-3, 'Sufficient decrease not achieved')

0 commit comments

Comments
 (0)