You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

298 lines
11 KiB
Python

"""
Unit test for Linear Programming via Simplex Algorithm.
"""
import numpy as np
from numpy.testing import assert_, assert_allclose, assert_equal
from pytest import raises as assert_raises
from scipy.optimize._linprog_util import _clean_inputs, _LPProblem
from copy import deepcopy
from datetime import date
def test_aliasing():
"""
Test for ensuring that no objects referred to by `lp` attributes,
`c`, `A_ub`, `b_ub`, `A_eq`, `b_eq`, `bounds`, have been modified
by `_clean_inputs` as a side effect.
"""
lp = _LPProblem(
c=1,
A_ub=[[1]],
b_ub=[1],
A_eq=[[1]],
b_eq=[1],
bounds=(-np.inf, np.inf)
)
lp_copy = deepcopy(lp)
_clean_inputs(lp)
assert_(lp.c == lp_copy.c, "c modified by _clean_inputs")
assert_(lp.A_ub == lp_copy.A_ub, "A_ub modified by _clean_inputs")
assert_(lp.b_ub == lp_copy.b_ub, "b_ub modified by _clean_inputs")
assert_(lp.A_eq == lp_copy.A_eq, "A_eq modified by _clean_inputs")
assert_(lp.b_eq == lp_copy.b_eq, "b_eq modified by _clean_inputs")
assert_(lp.bounds == lp_copy.bounds, "bounds modified by _clean_inputs")
def test_aliasing2():
"""
Similar purpose as `test_aliasing` above.
"""
lp = _LPProblem(
c=np.array([1, 1]),
A_ub=np.array([[1, 1], [2, 2]]),
b_ub=np.array([[1], [1]]),
A_eq=np.array([[1, 1]]),
b_eq=np.array([1]),
bounds=[(-np.inf, np.inf), (None, 1)]
)
lp_copy = deepcopy(lp)
_clean_inputs(lp)
assert_allclose(lp.c, lp_copy.c, err_msg="c modified by _clean_inputs")
assert_allclose(lp.A_ub, lp_copy.A_ub, err_msg="A_ub modified by _clean_inputs")
assert_allclose(lp.b_ub, lp_copy.b_ub, err_msg="b_ub modified by _clean_inputs")
assert_allclose(lp.A_eq, lp_copy.A_eq, err_msg="A_eq modified by _clean_inputs")
assert_allclose(lp.b_eq, lp_copy.b_eq, err_msg="b_eq modified by _clean_inputs")
assert_(lp.bounds == lp_copy.bounds, "bounds modified by _clean_inputs")
def test_missing_inputs():
c = [1, 2]
A_ub = np.array([[1, 1], [2, 2]])
b_ub = np.array([1, 1])
A_eq = np.array([[1, 1], [2, 2]])
b_eq = np.array([1, 1])
assert_raises(TypeError, _clean_inputs)
assert_raises(TypeError, _clean_inputs, _LPProblem(c=None))
assert_raises(ValueError, _clean_inputs, _LPProblem(c=c, A_ub=A_ub))
assert_raises(ValueError, _clean_inputs, _LPProblem(c=c, A_ub=A_ub, b_ub=None))
assert_raises(ValueError, _clean_inputs, _LPProblem(c=c, b_ub=b_ub))
assert_raises(ValueError, _clean_inputs, _LPProblem(c=c, A_ub=None, b_ub=b_ub))
assert_raises(ValueError, _clean_inputs, _LPProblem(c=c, A_eq=A_eq))
assert_raises(ValueError, _clean_inputs, _LPProblem(c=c, A_eq=A_eq, b_eq=None))
assert_raises(ValueError, _clean_inputs, _LPProblem(c=c, b_eq=b_eq))
assert_raises(ValueError, _clean_inputs, _LPProblem(c=c, A_eq=None, b_eq=b_eq))
def test_too_many_dimensions():
cb = [1, 2, 3, 4]
A = np.random.rand(4, 4)
bad2D = [[1, 2], [3, 4]]
bad3D = np.random.rand(4, 4, 4)
assert_raises(ValueError, _clean_inputs, _LPProblem(c=bad2D, A_ub=A, b_ub=cb))
assert_raises(ValueError, _clean_inputs, _LPProblem(c=cb, A_ub=bad3D, b_ub=cb))
assert_raises(ValueError, _clean_inputs, _LPProblem(c=cb, A_ub=A, b_ub=bad2D))
assert_raises(ValueError, _clean_inputs, _LPProblem(c=cb, A_eq=bad3D, b_eq=cb))
assert_raises(ValueError, _clean_inputs, _LPProblem(c=cb, A_eq=A, b_eq=bad2D))
def test_too_few_dimensions():
bad = np.random.rand(4, 4).ravel()
cb = np.random.rand(4)
assert_raises(ValueError, _clean_inputs, _LPProblem(c=cb, A_ub=bad, b_ub=cb))
assert_raises(ValueError, _clean_inputs, _LPProblem(c=cb, A_eq=bad, b_eq=cb))
def test_inconsistent_dimensions():
m = 2
n = 4
c = [1, 2, 3, 4]
Agood = np.random.rand(m, n)
Abad = np.random.rand(m, n + 1)
bgood = np.random.rand(m)
bbad = np.random.rand(m + 1)
boundsbad = [(0, 1)] * (n + 1)
assert_raises(ValueError, _clean_inputs, _LPProblem(c=c, A_ub=Abad, b_ub=bgood))
assert_raises(ValueError, _clean_inputs, _LPProblem(c=c, A_ub=Agood, b_ub=bbad))
assert_raises(ValueError, _clean_inputs, _LPProblem(c=c, A_eq=Abad, b_eq=bgood))
assert_raises(ValueError, _clean_inputs, _LPProblem(c=c, A_eq=Agood, b_eq=bbad))
assert_raises(ValueError, _clean_inputs, _LPProblem(c=c, bounds=boundsbad))
assert_raises(ValueError, _clean_inputs, _LPProblem(c=c, bounds=[[1, 2], [2, 3], [3, 4], [4, 5, 6]]))
def test_type_errors():
lp = _LPProblem(
c=[1, 2],
A_ub=np.array([[1, 1], [2, 2]]),
b_ub=np.array([1, 1]),
A_eq=np.array([[1, 1], [2, 2]]),
b_eq=np.array([1, 1]),
bounds=[(0, 1)]
)
bad = "hello"
assert_raises(TypeError, _clean_inputs, lp._replace(c=bad))
assert_raises(TypeError, _clean_inputs, lp._replace(A_ub=bad))
assert_raises(TypeError, _clean_inputs, lp._replace(b_ub=bad))
assert_raises(TypeError, _clean_inputs, lp._replace(A_eq=bad))
assert_raises(TypeError, _clean_inputs, lp._replace(b_eq=bad))
assert_raises(ValueError, _clean_inputs, lp._replace(bounds=bad))
assert_raises(ValueError, _clean_inputs, lp._replace(bounds="hi"))
assert_raises(ValueError, _clean_inputs, lp._replace(bounds=["hi"]))
assert_raises(ValueError, _clean_inputs, lp._replace(bounds=[("hi")]))
assert_raises(ValueError, _clean_inputs, lp._replace(bounds=[(1, "")]))
assert_raises(ValueError, _clean_inputs, lp._replace(bounds=[(1, 2), (1, "")]))
assert_raises(TypeError, _clean_inputs, lp._replace(bounds=[(1, date(2020, 2, 29))]))
assert_raises(ValueError, _clean_inputs, lp._replace(bounds=[[[1, 2]]]))
def test_non_finite_errors():
lp = _LPProblem(
c=[1, 2],
A_ub=np.array([[1, 1], [2, 2]]),
b_ub=np.array([1, 1]),
A_eq=np.array([[1, 1], [2, 2]]),
b_eq=np.array([1, 1]),
bounds=[(0, 1)]
)
assert_raises(ValueError, _clean_inputs, lp._replace(c=[0, None]))
assert_raises(ValueError, _clean_inputs, lp._replace(c=[np.inf, 0]))
assert_raises(ValueError, _clean_inputs, lp._replace(c=[0, -np.inf]))
assert_raises(ValueError, _clean_inputs, lp._replace(c=[np.nan, 0]))
assert_raises(ValueError, _clean_inputs, lp._replace(A_ub=[[1, 2], [None, 1]]))
assert_raises(ValueError, _clean_inputs, lp._replace(b_ub=[np.inf, 1]))
assert_raises(ValueError, _clean_inputs, lp._replace(A_eq=[[1, 2], [1, -np.inf]]))
assert_raises(ValueError, _clean_inputs, lp._replace(b_eq=[1, np.nan]))
def test__clean_inputs1():
lp = _LPProblem(
c=[1, 2],
A_ub=[[1, 1], [2, 2]],
b_ub=[1, 1],
A_eq=[[1, 1], [2, 2]],
b_eq=[1, 1],
bounds=None
)
lp_cleaned = _clean_inputs(lp)
assert_allclose(lp_cleaned.c, np.array(lp.c))
assert_allclose(lp_cleaned.A_ub, np.array(lp.A_ub))
assert_allclose(lp_cleaned.b_ub, np.array(lp.b_ub))
assert_allclose(lp_cleaned.A_eq, np.array(lp.A_eq))
assert_allclose(lp_cleaned.b_eq, np.array(lp.b_eq))
assert_equal(lp_cleaned.bounds, [(0, np.inf)] * 2)
assert_(lp_cleaned.c.shape == (2,), "")
assert_(lp_cleaned.A_ub.shape == (2, 2), "")
assert_(lp_cleaned.b_ub.shape == (2,), "")
assert_(lp_cleaned.A_eq.shape == (2, 2), "")
assert_(lp_cleaned.b_eq.shape == (2,), "")
def test__clean_inputs2():
lp = _LPProblem(
c=1,
A_ub=[[1]],
b_ub=1,
A_eq=[[1]],
b_eq=1,
bounds=(0, 1)
)
lp_cleaned = _clean_inputs(lp)
assert_allclose(lp_cleaned.c, np.array(lp.c))
assert_allclose(lp_cleaned.A_ub, np.array(lp.A_ub))
assert_allclose(lp_cleaned.b_ub, np.array(lp.b_ub))
assert_allclose(lp_cleaned.A_eq, np.array(lp.A_eq))
assert_allclose(lp_cleaned.b_eq, np.array(lp.b_eq))
assert_equal(lp_cleaned.bounds, [(0, 1)])
assert_(lp_cleaned.c.shape == (1,), "")
assert_(lp_cleaned.A_ub.shape == (1, 1), "")
assert_(lp_cleaned.b_ub.shape == (1,), "")
assert_(lp_cleaned.A_eq.shape == (1, 1), "")
assert_(lp_cleaned.b_eq.shape == (1,), "")
def test__clean_inputs3():
lp = _LPProblem(
c=[[1, 2]],
A_ub=np.random.rand(2, 2),
b_ub=[[1], [2]],
A_eq=np.random.rand(2, 2),
b_eq=[[1], [2]],
bounds=[(0, 1)]
)
lp_cleaned = _clean_inputs(lp)
assert_allclose(lp_cleaned.c, np.array([1, 2]))
assert_allclose(lp_cleaned.b_ub, np.array([1, 2]))
assert_allclose(lp_cleaned.b_eq, np.array([1, 2]))
assert_equal(lp_cleaned.bounds, [(0, 1)] * 2)
assert_(lp_cleaned.c.shape == (2,), "")
assert_(lp_cleaned.b_ub.shape == (2,), "")
assert_(lp_cleaned.b_eq.shape == (2,), "")
def test_bad_bounds():
lp = _LPProblem(c=[1, 2])
assert_raises(ValueError, _clean_inputs, lp._replace(bounds=(1, 2, 2)))
assert_raises(ValueError, _clean_inputs, lp._replace(bounds=[(1, 2, 2)]))
assert_raises(ValueError, _clean_inputs, lp._replace(bounds=[(1, 2), (1, 2, 2)]))
assert_raises(ValueError, _clean_inputs, lp._replace(bounds=[(1, 2), (1, 2), (1, 2)]))
lp = _LPProblem(c=[1, 2, 3, 4])
assert_raises(ValueError, _clean_inputs, lp._replace(bounds=[(1, 2, 3, 4), (1, 2, 3, 4)]))
def test_good_bounds():
lp = _LPProblem(c=[1, 2])
lp_cleaned = _clean_inputs(lp) # lp.bounds is None by default
assert_equal(lp_cleaned.bounds, [(0, np.inf)] * 2)
lp_cleaned = _clean_inputs(lp._replace(bounds=[]))
assert_equal(lp_cleaned.bounds, [(0, np.inf)] * 2)
lp_cleaned = _clean_inputs(lp._replace(bounds=[[]]))
assert_equal(lp_cleaned.bounds, [(0, np.inf)] * 2)
lp_cleaned = _clean_inputs(lp._replace(bounds=(1, 2)))
assert_equal(lp_cleaned.bounds, [(1, 2)] * 2)
lp_cleaned = _clean_inputs(lp._replace(bounds=[(1, 2)]))
assert_equal(lp_cleaned.bounds, [(1, 2)] * 2)
lp_cleaned = _clean_inputs(lp._replace(bounds=[(1, None)]))
assert_equal(lp_cleaned.bounds, [(1, np.inf)] * 2)
lp_cleaned = _clean_inputs(lp._replace(bounds=[(None, 1)]))
assert_equal(lp_cleaned.bounds, [(-np.inf, 1)] * 2)
lp_cleaned = _clean_inputs(lp._replace(bounds=[(None, None), (-np.inf, None)]))
assert_equal(lp_cleaned.bounds, [(-np.inf, np.inf)] * 2)
lp = _LPProblem(c=[1, 2, 3, 4])
lp_cleaned = _clean_inputs(lp) # lp.bounds is None by default
assert_equal(lp_cleaned.bounds, [(0, np.inf)] * 4)
lp_cleaned = _clean_inputs(lp._replace(bounds=(1, 2)))
assert_equal(lp_cleaned.bounds, [(1, 2)] * 4)
lp_cleaned = _clean_inputs(lp._replace(bounds=[(1, 2)]))
assert_equal(lp_cleaned.bounds, [(1, 2)] * 4)
lp_cleaned = _clean_inputs(lp._replace(bounds=[(1, None)]))
assert_equal(lp_cleaned.bounds, [(1, np.inf)] * 4)
lp_cleaned = _clean_inputs(lp._replace(bounds=[(None, 1)]))
assert_equal(lp_cleaned.bounds, [(-np.inf, 1)] * 4)
lp_cleaned = _clean_inputs(lp._replace(bounds=[(None, None), (-np.inf, None), (None, np.inf), (-np.inf, np.inf)]))
assert_equal(lp_cleaned.bounds, [(-np.inf, np.inf)] * 4)