test__remove_redundancy.py 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. """
  2. Unit test for Linear Programming via Simplex Algorithm.
  3. """
  4. # TODO: add tests for:
  5. # https://github.com/scipy/scipy/issues/5400
  6. # https://github.com/scipy/scipy/issues/6690
  7. from __future__ import division, print_function, absolute_import
  8. import numpy as np
  9. from numpy.testing import (
  10. assert_,
  11. assert_allclose,
  12. assert_equal)
  13. from .test_linprog import magic_square
  14. from scipy.optimize._remove_redundancy import _remove_redundancy
  15. def setup_module():
  16. np.random.seed(2017)
  17. def _assert_success(
  18. res,
  19. desired_fun=None,
  20. desired_x=None,
  21. rtol=1e-7,
  22. atol=1e-7):
  23. # res: linprog result object
  24. # desired_fun: desired objective function value or None
  25. # desired_x: desired solution or None
  26. assert_(res.success)
  27. assert_equal(res.status, 0)
  28. if desired_fun is not None:
  29. assert_allclose(
  30. res.fun,
  31. desired_fun,
  32. err_msg="converged to an unexpected objective value",
  33. rtol=rtol,
  34. atol=atol)
  35. if desired_x is not None:
  36. assert_allclose(
  37. res.x,
  38. desired_x,
  39. err_msg="converged to an unexpected solution",
  40. rtol=rtol,
  41. atol=atol)
  42. def test_no_redundancy():
  43. m, n = 10, 10
  44. A0 = np.random.rand(m, n)
  45. b0 = np.random.rand(m)
  46. A1, b1, status, message = _remove_redundancy(A0, b0)
  47. assert_allclose(A0, A1)
  48. assert_allclose(b0, b1)
  49. assert_equal(status, 0)
  50. def test_infeasible_zero_row():
  51. A = np.eye(3)
  52. A[1, :] = 0
  53. b = np.random.rand(3)
  54. A1, b1, status, message = _remove_redundancy(A, b)
  55. assert_equal(status, 2)
  56. def test_remove_zero_row():
  57. A = np.eye(3)
  58. A[1, :] = 0
  59. b = np.random.rand(3)
  60. b[1] = 0
  61. A1, b1, status, message = _remove_redundancy(A, b)
  62. assert_equal(status, 0)
  63. assert_allclose(A1, A[[0, 2], :])
  64. assert_allclose(b1, b[[0, 2]])
  65. def test_infeasible_m_gt_n():
  66. m, n = 20, 10
  67. A0 = np.random.rand(m, n)
  68. b0 = np.random.rand(m)
  69. A1, b1, status, message = _remove_redundancy(A0, b0)
  70. assert_equal(status, 2)
  71. def test_infeasible_m_eq_n():
  72. m, n = 10, 10
  73. A0 = np.random.rand(m, n)
  74. b0 = np.random.rand(m)
  75. A0[-1, :] = 2 * A0[-2, :]
  76. A1, b1, status, message = _remove_redundancy(A0, b0)
  77. assert_equal(status, 2)
  78. def test_infeasible_m_lt_n():
  79. m, n = 9, 10
  80. A0 = np.random.rand(m, n)
  81. b0 = np.random.rand(m)
  82. A0[-1, :] = np.arange(m - 1).dot(A0[:-1])
  83. A1, b1, status, message = _remove_redundancy(A0, b0)
  84. assert_equal(status, 2)
  85. def test_m_gt_n():
  86. np.random.seed(2032)
  87. m, n = 20, 10
  88. A0 = np.random.rand(m, n)
  89. b0 = np.random.rand(m)
  90. x = np.linalg.solve(A0[:n, :], b0[:n])
  91. b0[n:] = A0[n:, :].dot(x)
  92. A1, b1, status, message = _remove_redundancy(A0, b0)
  93. assert_equal(status, 0)
  94. assert_equal(A1.shape[0], n)
  95. assert_equal(np.linalg.matrix_rank(A1), n)
  96. def test_m_gt_n_rank_deficient():
  97. m, n = 20, 10
  98. A0 = np.zeros((m, n))
  99. A0[:, 0] = 1
  100. b0 = np.ones(m)
  101. A1, b1, status, message = _remove_redundancy(A0, b0)
  102. assert_equal(status, 0)
  103. assert_allclose(A1, A0[0:1, :])
  104. assert_allclose(b1, b0[0])
  105. def test_m_lt_n_rank_deficient():
  106. m, n = 9, 10
  107. A0 = np.random.rand(m, n)
  108. b0 = np.random.rand(m)
  109. A0[-1, :] = np.arange(m - 1).dot(A0[:-1])
  110. b0[-1] = np.arange(m - 1).dot(b0[:-1])
  111. A1, b1, status, message = _remove_redundancy(A0, b0)
  112. assert_equal(status, 0)
  113. assert_equal(A1.shape[0], 8)
  114. assert_equal(np.linalg.matrix_rank(A1), 8)
  115. def test_dense1():
  116. A = np.ones((6, 6))
  117. A[0, :3] = 0
  118. A[1, 3:] = 0
  119. A[3:, ::2] = -1
  120. A[3, :2] = 0
  121. A[4, 2:] = 0
  122. b = np.zeros(A.shape[0])
  123. A2 = A[[0, 1, 3, 4], :]
  124. b2 = np.zeros(4)
  125. A1, b1, status, message = _remove_redundancy(A, b)
  126. assert_allclose(A1, A2)
  127. assert_allclose(b1, b2)
  128. assert_equal(status, 0)
  129. def test_dense2():
  130. A = np.eye(6)
  131. A[-2, -1] = 1
  132. A[-1, :] = 1
  133. b = np.zeros(A.shape[0])
  134. A1, b1, status, message = _remove_redundancy(A, b)
  135. assert_allclose(A1, A[:-1, :])
  136. assert_allclose(b1, b[:-1])
  137. assert_equal(status, 0)
  138. def test_dense3():
  139. A = np.eye(6)
  140. A[-2, -1] = 1
  141. A[-1, :] = 1
  142. b = np.random.rand(A.shape[0])
  143. b[-1] = np.sum(b[:-1])
  144. A1, b1, status, message = _remove_redundancy(A, b)
  145. assert_allclose(A1, A[:-1, :])
  146. assert_allclose(b1, b[:-1])
  147. assert_equal(status, 0)
  148. def test_m_gt_n_sparse():
  149. np.random.seed(2013)
  150. m, n = 20, 5
  151. p = 0.1
  152. A = np.random.rand(m, n)
  153. A[np.random.rand(m, n) > p] = 0
  154. rank = np.linalg.matrix_rank(A)
  155. b = np.zeros(A.shape[0])
  156. A1, b1, status, message = _remove_redundancy(A, b)
  157. assert_equal(status, 0)
  158. assert_equal(A1.shape[0], rank)
  159. assert_equal(np.linalg.matrix_rank(A1), rank)
  160. def test_m_lt_n_sparse():
  161. np.random.seed(2017)
  162. m, n = 20, 50
  163. p = 0.05
  164. A = np.random.rand(m, n)
  165. A[np.random.rand(m, n) > p] = 0
  166. rank = np.linalg.matrix_rank(A)
  167. b = np.zeros(A.shape[0])
  168. A1, b1, status, message = _remove_redundancy(A, b)
  169. assert_equal(status, 0)
  170. assert_equal(A1.shape[0], rank)
  171. assert_equal(np.linalg.matrix_rank(A1), rank)
  172. def test_m_eq_n_sparse():
  173. np.random.seed(2017)
  174. m, n = 100, 100
  175. p = 0.01
  176. A = np.random.rand(m, n)
  177. A[np.random.rand(m, n) > p] = 0
  178. rank = np.linalg.matrix_rank(A)
  179. b = np.zeros(A.shape[0])
  180. A1, b1, status, message = _remove_redundancy(A, b)
  181. assert_equal(status, 0)
  182. assert_equal(A1.shape[0], rank)
  183. assert_equal(np.linalg.matrix_rank(A1), rank)
  184. def test_magic_square():
  185. A, b, c, numbers = magic_square(3)
  186. A1, b1, status, message = _remove_redundancy(A, b)
  187. assert_equal(status, 0)
  188. assert_equal(A1.shape[0], 23)
  189. assert_equal(np.linalg.matrix_rank(A1), 23)
  190. def test_magic_square2():
  191. A, b, c, numbers = magic_square(4)
  192. A1, b1, status, message = _remove_redundancy(A, b)
  193. assert_equal(status, 0)
  194. assert_equal(A1.shape[0], 39)
  195. assert_equal(np.linalg.matrix_rank(A1), 39)