test_tnc.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. """
  2. Unit tests for TNC optimization routine from tnc.py
  3. """
  4. from numpy.testing import assert_allclose, assert_equal
  5. from scipy import optimize
  6. import numpy as np
  7. from math import pow
  8. class TestTnc(object):
  9. """TNC non-linear optimization.
  10. These tests are taken from Prof. K. Schittkowski's test examples
  11. for constrained non-linear programming.
  12. http://www.uni-bayreuth.de/departments/math/~kschittkowski/home.htm
  13. """
  14. def setup_method(self):
  15. # options for minimize
  16. self.opts = {'disp': False, 'maxiter': 200}
  17. # objective functions and jacobian for each test
  18. def f1(self, x, a=100.0):
  19. return a * pow((x[1] - pow(x[0], 2)), 2) + pow(1.0 - x[0], 2)
  20. def g1(self, x, a=100.0):
  21. dif = [0, 0]
  22. dif[1] = 2 * a * (x[1] - pow(x[0], 2))
  23. dif[0] = -2.0 * (x[0] * (dif[1] - 1.0) + 1.0)
  24. return dif
  25. def fg1(self, x, a=100.0):
  26. return self.f1(x, a), self.g1(x, a)
  27. def f3(self, x):
  28. return x[1] + pow(x[1] - x[0], 2) * 1.0e-5
  29. def g3(self, x):
  30. dif = [0, 0]
  31. dif[0] = -2.0 * (x[1] - x[0]) * 1.0e-5
  32. dif[1] = 1.0 - dif[0]
  33. return dif
  34. def fg3(self, x):
  35. return self.f3(x), self.g3(x)
  36. def f4(self, x):
  37. return pow(x[0] + 1.0, 3) / 3.0 + x[1]
  38. def g4(self, x):
  39. dif = [0, 0]
  40. dif[0] = pow(x[0] + 1.0, 2)
  41. dif[1] = 1.0
  42. return dif
  43. def fg4(self, x):
  44. return self.f4(x), self.g4(x)
  45. def f5(self, x):
  46. return np.sin(x[0] + x[1]) + pow(x[0] - x[1], 2) - \
  47. 1.5 * x[0] + 2.5 * x[1] + 1.0
  48. def g5(self, x):
  49. dif = [0, 0]
  50. v1 = np.cos(x[0] + x[1])
  51. v2 = 2.0*(x[0] - x[1])
  52. dif[0] = v1 + v2 - 1.5
  53. dif[1] = v1 - v2 + 2.5
  54. return dif
  55. def fg5(self, x):
  56. return self.f5(x), self.g5(x)
  57. def f38(self, x):
  58. return (100.0 * pow(x[1] - pow(x[0], 2), 2) +
  59. pow(1.0 - x[0], 2) + 90.0 * pow(x[3] - pow(x[2], 2), 2) +
  60. pow(1.0 - x[2], 2) + 10.1 * (pow(x[1] - 1.0, 2) +
  61. pow(x[3] - 1.0, 2)) +
  62. 19.8 * (x[1] - 1.0) * (x[3] - 1.0)) * 1.0e-5
  63. def g38(self, x):
  64. dif = [0, 0, 0, 0]
  65. dif[0] = (-400.0 * x[0] * (x[1] - pow(x[0], 2)) -
  66. 2.0 * (1.0 - x[0])) * 1.0e-5
  67. dif[1] = (200.0 * (x[1] - pow(x[0], 2)) + 20.2 * (x[1] - 1.0) +
  68. 19.8 * (x[3] - 1.0)) * 1.0e-5
  69. dif[2] = (- 360.0 * x[2] * (x[3] - pow(x[2], 2)) -
  70. 2.0 * (1.0 - x[2])) * 1.0e-5
  71. dif[3] = (180.0 * (x[3] - pow(x[2], 2)) + 20.2 * (x[3] - 1.0) +
  72. 19.8 * (x[1] - 1.0)) * 1.0e-5
  73. return dif
  74. def fg38(self, x):
  75. return self.f38(x), self.g38(x)
  76. def f45(self, x):
  77. return 2.0 - x[0] * x[1] * x[2] * x[3] * x[4] / 120.0
  78. def g45(self, x):
  79. dif = [0] * 5
  80. dif[0] = - x[1] * x[2] * x[3] * x[4] / 120.0
  81. dif[1] = - x[0] * x[2] * x[3] * x[4] / 120.0
  82. dif[2] = - x[0] * x[1] * x[3] * x[4] / 120.0
  83. dif[3] = - x[0] * x[1] * x[2] * x[4] / 120.0
  84. dif[4] = - x[0] * x[1] * x[2] * x[3] / 120.0
  85. return dif
  86. def fg45(self, x):
  87. return self.f45(x), self.g45(x)
  88. # tests
  89. # minimize with method=TNC
  90. def test_minimize_tnc1(self):
  91. x0, bnds = [-2, 1], ([-np.inf, None], [-1.5, None])
  92. xopt = [1, 1]
  93. iterx = [] # to test callback
  94. res = optimize.minimize(self.f1, x0, method='TNC', jac=self.g1,
  95. bounds=bnds, options=self.opts,
  96. callback=iterx.append)
  97. assert_allclose(res.fun, self.f1(xopt), atol=1e-8)
  98. assert_equal(len(iterx), res.nit)
  99. def test_minimize_tnc1b(self):
  100. x0, bnds = np.matrix([-2, 1]), ([-np.inf, None],[-1.5, None])
  101. xopt = [1, 1]
  102. x = optimize.minimize(self.f1, x0, method='TNC',
  103. bounds=bnds, options=self.opts).x
  104. assert_allclose(self.f1(x), self.f1(xopt), atol=1e-4)
  105. def test_minimize_tnc1c(self):
  106. x0, bnds = [-2, 1], ([-np.inf, None],[-1.5, None])
  107. xopt = [1, 1]
  108. x = optimize.minimize(self.fg1, x0, method='TNC',
  109. jac=True, bounds=bnds,
  110. options=self.opts).x
  111. assert_allclose(self.f1(x), self.f1(xopt), atol=1e-8)
  112. def test_minimize_tnc2(self):
  113. x0, bnds = [-2, 1], ([-np.inf, None], [1.5, None])
  114. xopt = [-1.2210262419616387, 1.5]
  115. x = optimize.minimize(self.f1, x0, method='TNC',
  116. jac=self.g1, bounds=bnds,
  117. options=self.opts).x
  118. assert_allclose(self.f1(x), self.f1(xopt), atol=1e-8)
  119. def test_minimize_tnc3(self):
  120. x0, bnds = [10, 1], ([-np.inf, None], [0.0, None])
  121. xopt = [0, 0]
  122. x = optimize.minimize(self.f3, x0, method='TNC',
  123. jac=self.g3, bounds=bnds,
  124. options=self.opts).x
  125. assert_allclose(self.f3(x), self.f3(xopt), atol=1e-8)
  126. def test_minimize_tnc4(self):
  127. x0,bnds = [1.125, 0.125], [(1, None), (0, None)]
  128. xopt = [1, 0]
  129. x = optimize.minimize(self.f4, x0, method='TNC',
  130. jac=self.g4, bounds=bnds,
  131. options=self.opts).x
  132. assert_allclose(self.f4(x), self.f4(xopt), atol=1e-8)
  133. def test_minimize_tnc5(self):
  134. x0, bnds = [0, 0], [(-1.5, 4),(-3, 3)]
  135. xopt = [-0.54719755119659763, -1.5471975511965976]
  136. x = optimize.minimize(self.f5, x0, method='TNC',
  137. jac=self.g5, bounds=bnds,
  138. options=self.opts).x
  139. assert_allclose(self.f5(x), self.f5(xopt), atol=1e-8)
  140. def test_minimize_tnc38(self):
  141. x0, bnds = np.array([-3, -1, -3, -1]), [(-10, 10)]*4
  142. xopt = [1]*4
  143. x = optimize.minimize(self.f38, x0, method='TNC',
  144. jac=self.g38, bounds=bnds,
  145. options=self.opts).x
  146. assert_allclose(self.f38(x), self.f38(xopt), atol=1e-8)
  147. def test_minimize_tnc45(self):
  148. x0, bnds = [2] * 5, [(0, 1), (0, 2), (0, 3), (0, 4), (0, 5)]
  149. xopt = [1, 2, 3, 4, 5]
  150. x = optimize.minimize(self.f45, x0, method='TNC',
  151. jac=self.g45, bounds=bnds,
  152. options=self.opts).x
  153. assert_allclose(self.f45(x), self.f45(xopt), atol=1e-8)
  154. # fmin_tnc
  155. def test_tnc1(self):
  156. fg, x, bounds = self.fg1, [-2, 1], ([-np.inf, None], [-1.5, None])
  157. xopt = [1, 1]
  158. x, nf, rc = optimize.fmin_tnc(fg, x, bounds=bounds, args=(100.0, ),
  159. messages=optimize.tnc.MSG_NONE,
  160. maxfun=200)
  161. assert_allclose(self.f1(x), self.f1(xopt), atol=1e-8,
  162. err_msg="TNC failed with status: " +
  163. optimize.tnc.RCSTRINGS[rc])
  164. def test_tnc1b(self):
  165. x, bounds = [-2, 1], ([-np.inf, None], [-1.5, None])
  166. xopt = [1, 1]
  167. x, nf, rc = optimize.fmin_tnc(self.f1, x, approx_grad=True,
  168. bounds=bounds,
  169. messages=optimize.tnc.MSG_NONE,
  170. maxfun=200)
  171. assert_allclose(self.f1(x), self.f1(xopt), atol=1e-4,
  172. err_msg="TNC failed with status: " +
  173. optimize.tnc.RCSTRINGS[rc])
  174. def test_tnc1c(self):
  175. x, bounds = [-2, 1], ([-np.inf, None], [-1.5, None])
  176. xopt = [1, 1]
  177. x, nf, rc = optimize.fmin_tnc(self.f1, x, fprime=self.g1,
  178. bounds=bounds,
  179. messages=optimize.tnc.MSG_NONE,
  180. maxfun=200)
  181. assert_allclose(self.f1(x), self.f1(xopt), atol=1e-8,
  182. err_msg="TNC failed with status: " +
  183. optimize.tnc.RCSTRINGS[rc])
  184. def test_tnc2(self):
  185. fg, x, bounds = self.fg1, [-2, 1], ([-np.inf, None], [1.5, None])
  186. xopt = [-1.2210262419616387, 1.5]
  187. x, nf, rc = optimize.fmin_tnc(fg, x, bounds=bounds,
  188. messages=optimize.tnc.MSG_NONE,
  189. maxfun=200)
  190. assert_allclose(self.f1(x), self.f1(xopt), atol=1e-8,
  191. err_msg="TNC failed with status: " +
  192. optimize.tnc.RCSTRINGS[rc])
  193. def test_tnc3(self):
  194. fg, x, bounds = self.fg3, [10, 1], ([-np.inf, None], [0.0, None])
  195. xopt = [0, 0]
  196. x, nf, rc = optimize.fmin_tnc(fg, x, bounds=bounds,
  197. messages=optimize.tnc.MSG_NONE,
  198. maxfun=200)
  199. assert_allclose(self.f3(x), self.f3(xopt), atol=1e-8,
  200. err_msg="TNC failed with status: " +
  201. optimize.tnc.RCSTRINGS[rc])
  202. def test_tnc4(self):
  203. fg, x, bounds = self.fg4, [1.125, 0.125], [(1, None), (0, None)]
  204. xopt = [1, 0]
  205. x, nf, rc = optimize.fmin_tnc(fg, x, bounds=bounds,
  206. messages=optimize.tnc.MSG_NONE,
  207. maxfun=200)
  208. assert_allclose(self.f4(x), self.f4(xopt), atol=1e-8,
  209. err_msg="TNC failed with status: " +
  210. optimize.tnc.RCSTRINGS[rc])
  211. def test_tnc5(self):
  212. fg, x, bounds = self.fg5, [0, 0], [(-1.5, 4),(-3, 3)]
  213. xopt = [-0.54719755119659763, -1.5471975511965976]
  214. x, nf, rc = optimize.fmin_tnc(fg, x, bounds=bounds,
  215. messages=optimize.tnc.MSG_NONE,
  216. maxfun=200)
  217. assert_allclose(self.f5(x), self.f5(xopt), atol=1e-8,
  218. err_msg="TNC failed with status: " +
  219. optimize.tnc.RCSTRINGS[rc])
  220. def test_tnc38(self):
  221. fg, x, bounds = self.fg38, np.array([-3, -1, -3, -1]), [(-10, 10)]*4
  222. xopt = [1]*4
  223. x, nf, rc = optimize.fmin_tnc(fg, x, bounds=bounds,
  224. messages=optimize.tnc.MSG_NONE,
  225. maxfun=200)
  226. assert_allclose(self.f38(x), self.f38(xopt), atol=1e-8,
  227. err_msg="TNC failed with status: " +
  228. optimize.tnc.RCSTRINGS[rc])
  229. def test_tnc45(self):
  230. fg, x, bounds = self.fg45, [2] * 5, [(0, 1), (0, 2), (0, 3),
  231. (0, 4), (0, 5)]
  232. xopt = [1, 2, 3, 4, 5]
  233. x, nf, rc = optimize.fmin_tnc(fg, x, bounds=bounds,
  234. messages=optimize.tnc.MSG_NONE,
  235. maxfun=200)
  236. assert_allclose(self.f45(x), self.f45(xopt), atol=1e-8,
  237. err_msg="TNC failed with status: " +
  238. optimize.tnc.RCSTRINGS[rc])