test_trustregion_krylov.py 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. """
  2. Unit tests for Krylov space trust-region subproblem solver.
  3. To run it in its simplest form::
  4. nosetests test_optimize.py
  5. """
  6. import numpy as np
  7. from scipy.optimize._trlib import (get_trlib_quadratic_subproblem)
  8. from numpy.testing import (assert_,
  9. assert_almost_equal,
  10. assert_equal, assert_array_almost_equal)
  11. KrylovQP = get_trlib_quadratic_subproblem(tol_rel_i=1e-8, tol_rel_b=1e-6)
  12. KrylovQP_disp = get_trlib_quadratic_subproblem(tol_rel_i=1e-8, tol_rel_b=1e-6, disp=True)
  13. class TestKrylovQuadraticSubproblem:
  14. def test_for_the_easy_case(self):
  15. # `H` is chosen such that `g` is not orthogonal to the
  16. # eigenvector associated with the smallest eigenvalue.
  17. H = np.array([[1.0, 0.0, 4.0],
  18. [0.0, 2.0, 0.0],
  19. [4.0, 0.0, 3.0]])
  20. g = np.array([5.0, 0.0, 4.0])
  21. # Trust Radius
  22. trust_radius = 1.0
  23. # Solve Subproblem
  24. subprob = KrylovQP(x=0,
  25. fun=lambda x: 0,
  26. jac=lambda x: g,
  27. hess=lambda x: None,
  28. hessp=lambda x, y: H.dot(y))
  29. p, hits_boundary = subprob.solve(trust_radius)
  30. assert_array_almost_equal(p, np.array([-1.0, 0.0, 0.0]))
  31. assert_equal(hits_boundary, True)
  32. # check kkt satisfaction
  33. assert_almost_equal(
  34. np.linalg.norm(H.dot(p) + subprob.lam * p + g),
  35. 0.0)
  36. # check trust region constraint
  37. assert_almost_equal(np.linalg.norm(p), trust_radius)
  38. trust_radius = 0.5
  39. p, hits_boundary = subprob.solve(trust_radius)
  40. assert_array_almost_equal(p,
  41. np.array([-0.46125446, 0., -0.19298788]))
  42. assert_equal(hits_boundary, True)
  43. # check kkt satisfaction
  44. assert_almost_equal(
  45. np.linalg.norm(H.dot(p) + subprob.lam * p + g),
  46. 0.0)
  47. # check trust region constraint
  48. assert_almost_equal(np.linalg.norm(p), trust_radius)
  49. def test_for_the_hard_case(self):
  50. # `H` is chosen such that `g` is orthogonal to the
  51. # eigenvector associated with the smallest eigenvalue.
  52. H = np.array([[1.0, 0.0, 4.0],
  53. [0.0, 2.0, 0.0],
  54. [4.0, 0.0, 3.0]])
  55. g = np.array([0.0, 2.0, 0.0])
  56. # Trust Radius
  57. trust_radius = 1.0
  58. # Solve Subproblem
  59. subprob = KrylovQP(x=0,
  60. fun=lambda x: 0,
  61. jac=lambda x: g,
  62. hess=lambda x: None,
  63. hessp=lambda x, y: H.dot(y))
  64. p, hits_boundary = subprob.solve(trust_radius)
  65. assert_array_almost_equal(p, np.array([0.0, -1.0, 0.0]))
  66. # check kkt satisfaction
  67. assert_almost_equal(
  68. np.linalg.norm(H.dot(p) + subprob.lam * p + g),
  69. 0.0)
  70. # check trust region constraint
  71. assert_almost_equal(np.linalg.norm(p), trust_radius)
  72. trust_radius = 0.5
  73. p, hits_boundary = subprob.solve(trust_radius)
  74. assert_array_almost_equal(p, np.array([0.0, -0.5, 0.0]))
  75. # check kkt satisfaction
  76. assert_almost_equal(
  77. np.linalg.norm(H.dot(p) + subprob.lam * p + g),
  78. 0.0)
  79. # check trust region constraint
  80. assert_almost_equal(np.linalg.norm(p), trust_radius)
  81. def test_for_interior_convergence(self):
  82. H = np.array([[1.812159, 0.82687265, 0.21838879, -0.52487006, 0.25436988],
  83. [0.82687265, 2.66380283, 0.31508988, -0.40144163, 0.08811588],
  84. [0.21838879, 0.31508988, 2.38020726, -0.3166346, 0.27363867],
  85. [-0.52487006, -0.40144163, -0.3166346, 1.61927182, -0.42140166],
  86. [0.25436988, 0.08811588, 0.27363867, -0.42140166, 1.33243101]])
  87. g = np.array([0.75798952, 0.01421945, 0.33847612, 0.83725004, -0.47909534])
  88. trust_radius = 1.1
  89. # Solve Subproblem
  90. subprob = KrylovQP(x=0,
  91. fun=lambda x: 0,
  92. jac=lambda x: g,
  93. hess=lambda x: None,
  94. hessp=lambda x, y: H.dot(y))
  95. p, hits_boundary = subprob.solve(trust_radius)
  96. # check kkt satisfaction
  97. assert_almost_equal(
  98. np.linalg.norm(H.dot(p) + subprob.lam * p + g),
  99. 0.0)
  100. assert_array_almost_equal(p, [-0.68585435, 0.1222621, -0.22090999,
  101. -0.67005053, 0.31586769])
  102. assert_array_almost_equal(hits_boundary, False)
  103. def test_for_very_close_to_zero(self):
  104. H = np.array([[0.88547534, 2.90692271, 0.98440885, -0.78911503, -0.28035809],
  105. [2.90692271, -0.04618819, 0.32867263, -0.83737945, 0.17116396],
  106. [0.98440885, 0.32867263, -0.87355957, -0.06521957, -1.43030957],
  107. [-0.78911503, -0.83737945, -0.06521957, -1.645709, -0.33887298],
  108. [-0.28035809, 0.17116396, -1.43030957, -0.33887298, -1.68586978]])
  109. g = np.array([0, 0, 0, 0, 1e-6])
  110. trust_radius = 1.1
  111. # Solve Subproblem
  112. subprob = KrylovQP(x=0,
  113. fun=lambda x: 0,
  114. jac=lambda x: g,
  115. hess=lambda x: None,
  116. hessp=lambda x, y: H.dot(y))
  117. p, hits_boundary = subprob.solve(trust_radius)
  118. # check kkt satisfaction
  119. assert_almost_equal(
  120. np.linalg.norm(H.dot(p) + subprob.lam * p + g),
  121. 0.0)
  122. # check trust region constraint
  123. assert_almost_equal(np.linalg.norm(p), trust_radius)
  124. assert_array_almost_equal(p, [0.06910534, -0.01432721,
  125. -0.65311947, -0.23815972,
  126. -0.84954934])
  127. assert_array_almost_equal(hits_boundary, True)
  128. def test_disp(self, capsys):
  129. H = -np.eye(5)
  130. g = np.array([0, 0, 0, 0, 1e-6])
  131. trust_radius = 1.1
  132. subprob = KrylovQP_disp(x=0,
  133. fun=lambda x: 0,
  134. jac=lambda x: g,
  135. hess=lambda x: None,
  136. hessp=lambda x, y: H.dot(y))
  137. p, hits_boundary = subprob.solve(trust_radius)
  138. out, err = capsys.readouterr()
  139. assert_(out.startswith(' TR Solving trust region problem'), repr(out))