| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255 |
- """
- Unit test for Linear Programming via Simplex Algorithm.
- """
- # TODO: add tests for:
- # https://github.com/scipy/scipy/issues/5400
- # https://github.com/scipy/scipy/issues/6690
- import numpy as np
- from numpy.testing import (
- assert_,
- assert_allclose,
- assert_equal)
- from .test_linprog import magic_square
- from scipy.optimize._remove_redundancy import _remove_redundancy_svd
- from scipy.optimize._remove_redundancy import _remove_redundancy_pivot_dense
- from scipy.optimize._remove_redundancy import _remove_redundancy_pivot_sparse
- from scipy.optimize._remove_redundancy import _remove_redundancy_id
- from scipy.sparse import csc_matrix
- def setup_module():
- np.random.seed(2017)
- def _assert_success(
- res,
- desired_fun=None,
- desired_x=None,
- rtol=1e-7,
- atol=1e-7):
- # res: linprog result object
- # desired_fun: desired objective function value or None
- # desired_x: desired solution or None
- assert_(res.success)
- assert_equal(res.status, 0)
- if desired_fun is not None:
- assert_allclose(
- res.fun,
- desired_fun,
- err_msg="converged to an unexpected objective value",
- rtol=rtol,
- atol=atol)
- if desired_x is not None:
- assert_allclose(
- res.x,
- desired_x,
- err_msg="converged to an unexpected solution",
- rtol=rtol,
- atol=atol)
- def redundancy_removed(A, B):
- """Checks whether a matrix contains only independent rows of another"""
- for rowA in A:
- # `rowA in B` is not a reliable check
- for rowB in B:
- if np.all(rowA == rowB):
- break
- else:
- return False
- return A.shape[0] == np.linalg.matrix_rank(A) == np.linalg.matrix_rank(B)
- class RRCommonTests:
- def test_no_redundancy(self):
- m, n = 10, 10
- A0 = np.random.rand(m, n)
- b0 = np.random.rand(m)
- A1, b1, status, message = self.rr(A0, b0)
- assert_allclose(A0, A1)
- assert_allclose(b0, b1)
- assert_equal(status, 0)
- def test_infeasible_zero_row(self):
- A = np.eye(3)
- A[1, :] = 0
- b = np.random.rand(3)
- A1, b1, status, message = self.rr(A, b)
- assert_equal(status, 2)
- def test_remove_zero_row(self):
- A = np.eye(3)
- A[1, :] = 0
- b = np.random.rand(3)
- b[1] = 0
- A1, b1, status, message = self.rr(A, b)
- assert_equal(status, 0)
- assert_allclose(A1, A[[0, 2], :])
- assert_allclose(b1, b[[0, 2]])
- def test_infeasible_m_gt_n(self):
- m, n = 20, 10
- A0 = np.random.rand(m, n)
- b0 = np.random.rand(m)
- A1, b1, status, message = self.rr(A0, b0)
- assert_equal(status, 2)
- def test_infeasible_m_eq_n(self):
- m, n = 10, 10
- A0 = np.random.rand(m, n)
- b0 = np.random.rand(m)
- A0[-1, :] = 2 * A0[-2, :]
- A1, b1, status, message = self.rr(A0, b0)
- assert_equal(status, 2)
- def test_infeasible_m_lt_n(self):
- m, n = 9, 10
- A0 = np.random.rand(m, n)
- b0 = np.random.rand(m)
- A0[-1, :] = np.arange(m - 1).dot(A0[:-1])
- A1, b1, status, message = self.rr(A0, b0)
- assert_equal(status, 2)
- def test_m_gt_n(self):
- np.random.seed(2032)
- m, n = 20, 10
- A0 = np.random.rand(m, n)
- b0 = np.random.rand(m)
- x = np.linalg.solve(A0[:n, :], b0[:n])
- b0[n:] = A0[n:, :].dot(x)
- A1, b1, status, message = self.rr(A0, b0)
- assert_equal(status, 0)
- assert_equal(A1.shape[0], n)
- assert_equal(np.linalg.matrix_rank(A1), n)
- def test_m_gt_n_rank_deficient(self):
- m, n = 20, 10
- A0 = np.zeros((m, n))
- A0[:, 0] = 1
- b0 = np.ones(m)
- A1, b1, status, message = self.rr(A0, b0)
- assert_equal(status, 0)
- assert_allclose(A1, A0[0:1, :])
- assert_allclose(b1, b0[0])
- def test_m_lt_n_rank_deficient(self):
- m, n = 9, 10
- A0 = np.random.rand(m, n)
- b0 = np.random.rand(m)
- A0[-1, :] = np.arange(m - 1).dot(A0[:-1])
- b0[-1] = np.arange(m - 1).dot(b0[:-1])
- A1, b1, status, message = self.rr(A0, b0)
- assert_equal(status, 0)
- assert_equal(A1.shape[0], 8)
- assert_equal(np.linalg.matrix_rank(A1), 8)
- def test_dense1(self):
- A = np.ones((6, 6))
- A[0, :3] = 0
- A[1, 3:] = 0
- A[3:, ::2] = -1
- A[3, :2] = 0
- A[4, 2:] = 0
- b = np.zeros(A.shape[0])
- A1, b1, status, message = self.rr(A, b)
- assert_(redundancy_removed(A1, A))
- assert_equal(status, 0)
- def test_dense2(self):
- A = np.eye(6)
- A[-2, -1] = 1
- A[-1, :] = 1
- b = np.zeros(A.shape[0])
- A1, b1, status, message = self.rr(A, b)
- assert_(redundancy_removed(A1, A))
- assert_equal(status, 0)
- def test_dense3(self):
- A = np.eye(6)
- A[-2, -1] = 1
- A[-1, :] = 1
- b = np.random.rand(A.shape[0])
- b[-1] = np.sum(b[:-1])
- A1, b1, status, message = self.rr(A, b)
- assert_(redundancy_removed(A1, A))
- assert_equal(status, 0)
- def test_m_gt_n_sparse(self):
- np.random.seed(2013)
- m, n = 20, 5
- p = 0.1
- A = np.random.rand(m, n)
- A[np.random.rand(m, n) > p] = 0
- rank = np.linalg.matrix_rank(A)
- b = np.zeros(A.shape[0])
- A1, b1, status, message = self.rr(A, b)
- assert_equal(status, 0)
- assert_equal(A1.shape[0], rank)
- assert_equal(np.linalg.matrix_rank(A1), rank)
- def test_m_lt_n_sparse(self):
- np.random.seed(2017)
- m, n = 20, 50
- p = 0.05
- A = np.random.rand(m, n)
- A[np.random.rand(m, n) > p] = 0
- rank = np.linalg.matrix_rank(A)
- b = np.zeros(A.shape[0])
- A1, b1, status, message = self.rr(A, b)
- assert_equal(status, 0)
- assert_equal(A1.shape[0], rank)
- assert_equal(np.linalg.matrix_rank(A1), rank)
- def test_m_eq_n_sparse(self):
- np.random.seed(2017)
- m, n = 100, 100
- p = 0.01
- A = np.random.rand(m, n)
- A[np.random.rand(m, n) > p] = 0
- rank = np.linalg.matrix_rank(A)
- b = np.zeros(A.shape[0])
- A1, b1, status, message = self.rr(A, b)
- assert_equal(status, 0)
- assert_equal(A1.shape[0], rank)
- assert_equal(np.linalg.matrix_rank(A1), rank)
- def test_magic_square(self):
- A, b, c, numbers, _ = magic_square(3)
- A1, b1, status, message = self.rr(A, b)
- assert_equal(status, 0)
- assert_equal(A1.shape[0], 23)
- assert_equal(np.linalg.matrix_rank(A1), 23)
- def test_magic_square2(self):
- A, b, c, numbers, _ = magic_square(4)
- A1, b1, status, message = self.rr(A, b)
- assert_equal(status, 0)
- assert_equal(A1.shape[0], 39)
- assert_equal(np.linalg.matrix_rank(A1), 39)
- class TestRRSVD(RRCommonTests):
- def rr(self, A, b):
- return _remove_redundancy_svd(A, b)
- class TestRRPivotDense(RRCommonTests):
- def rr(self, A, b):
- return _remove_redundancy_pivot_dense(A, b)
- class TestRRID(RRCommonTests):
- def rr(self, A, b):
- return _remove_redundancy_id(A, b)
- class TestRRPivotSparse(RRCommonTests):
- def rr(self, A, b):
- rr_res = _remove_redundancy_pivot_sparse(csc_matrix(A), b)
- A1, b1, status, message = rr_res
- return A1.toarray(), b1, status, message
|