123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444 |
- """
- Tests for the basic functionality of the SDM class.
- """
- from itertools import product
- from sympy.core.singleton import S
- from sympy.external.gmpy import HAS_GMPY
- from sympy.testing.pytest import raises
- from sympy.polys.domains import QQ, ZZ, EXRAW
- from sympy.polys.matrices.sdm import SDM
- from sympy.polys.matrices.ddm import DDM
- from sympy.polys.matrices.exceptions import (DMBadInputError, DMDomainError,
- DMShapeError)
- def test_SDM():
- A = SDM({0:{0:ZZ(1)}}, (2, 2), ZZ)
- assert A.domain == ZZ
- assert A.shape == (2, 2)
- assert dict(A) == {0:{0:ZZ(1)}}
- raises(DMBadInputError, lambda: SDM({5:{1:ZZ(0)}}, (2, 2), ZZ))
- raises(DMBadInputError, lambda: SDM({0:{5:ZZ(0)}}, (2, 2), ZZ))
- def test_DDM_str():
- sdm = SDM({0:{0:ZZ(1)}, 1:{1:ZZ(1)}}, (2, 2), ZZ)
- assert str(sdm) == '{0: {0: 1}, 1: {1: 1}}'
- if HAS_GMPY: # pragma: no cover
- assert repr(sdm) == 'SDM({0: {0: mpz(1)}, 1: {1: mpz(1)}}, (2, 2), ZZ)'
- else: # pragma: no cover
- assert repr(sdm) == 'SDM({0: {0: 1}, 1: {1: 1}}, (2, 2), ZZ)'
- def test_SDM_new():
- A = SDM({0:{0:ZZ(1)}}, (2, 2), ZZ)
- B = A.new({}, (2, 2), ZZ)
- assert B == SDM({}, (2, 2), ZZ)
- def test_SDM_copy():
- A = SDM({0:{0:ZZ(1)}}, (2, 2), ZZ)
- B = A.copy()
- assert A == B
- A[0][0] = ZZ(2)
- assert A != B
- def test_SDM_from_list():
- A = SDM.from_list([[ZZ(0), ZZ(1)], [ZZ(1), ZZ(0)]], (2, 2), ZZ)
- assert A == SDM({0:{1:ZZ(1)}, 1:{0:ZZ(1)}}, (2, 2), ZZ)
- raises(DMBadInputError, lambda: SDM.from_list([[ZZ(0)], [ZZ(0), ZZ(1)]], (2, 2), ZZ))
- raises(DMBadInputError, lambda: SDM.from_list([[ZZ(0), ZZ(1)]], (2, 2), ZZ))
- def test_SDM_to_list():
- A = SDM({0:{1: ZZ(1)}}, (2, 2), ZZ)
- assert A.to_list() == [[ZZ(0), ZZ(1)], [ZZ(0), ZZ(0)]]
- A = SDM({}, (0, 2), ZZ)
- assert A.to_list() == []
- A = SDM({}, (2, 0), ZZ)
- assert A.to_list() == [[], []]
- def test_SDM_to_list_flat():
- A = SDM({0:{1: ZZ(1)}}, (2, 2), ZZ)
- assert A.to_list_flat() == [ZZ(0), ZZ(1), ZZ(0), ZZ(0)]
- def test_SDM_to_dok():
- A = SDM({0:{1: ZZ(1)}}, (2, 2), ZZ)
- assert A.to_dok() == {(0, 1): ZZ(1)}
- def test_SDM_from_ddm():
- A = DDM([[ZZ(1), ZZ(0)], [ZZ(1), ZZ(0)]], (2, 2), ZZ)
- B = SDM.from_ddm(A)
- assert B.domain == ZZ
- assert B.shape == (2, 2)
- assert dict(B) == {0:{0:ZZ(1)}, 1:{0:ZZ(1)}}
- def test_SDM_to_ddm():
- A = SDM({0:{1: ZZ(1)}}, (2, 2), ZZ)
- B = DDM([[ZZ(0), ZZ(1)], [ZZ(0), ZZ(0)]], (2, 2), ZZ)
- assert A.to_ddm() == B
- def test_SDM_to_sdm():
- A = SDM({0:{1: ZZ(1)}}, (2, 2), ZZ)
- assert A.to_sdm() == A
- def test_SDM_getitem():
- A = SDM({0:{1:ZZ(1)}}, (2, 2), ZZ)
- assert A.getitem(0, 0) == ZZ.zero
- assert A.getitem(0, 1) == ZZ.one
- assert A.getitem(1, 0) == ZZ.zero
- assert A.getitem(-2, -2) == ZZ.zero
- assert A.getitem(-2, -1) == ZZ.one
- assert A.getitem(-1, -2) == ZZ.zero
- raises(IndexError, lambda: A.getitem(2, 0))
- raises(IndexError, lambda: A.getitem(0, 2))
- def test_SDM_setitem():
- A = SDM({0:{1:ZZ(1)}}, (2, 2), ZZ)
- A.setitem(0, 0, ZZ(1))
- assert A == SDM({0:{0:ZZ(1), 1:ZZ(1)}}, (2, 2), ZZ)
- A.setitem(1, 0, ZZ(1))
- assert A == SDM({0:{0:ZZ(1), 1:ZZ(1)}, 1:{0:ZZ(1)}}, (2, 2), ZZ)
- A.setitem(1, 0, ZZ(0))
- assert A == SDM({0:{0:ZZ(1), 1:ZZ(1)}}, (2, 2), ZZ)
- # Repeat the above test so that this time the row is empty
- A.setitem(1, 0, ZZ(0))
- assert A == SDM({0:{0:ZZ(1), 1:ZZ(1)}}, (2, 2), ZZ)
- A.setitem(0, 0, ZZ(0))
- assert A == SDM({0:{1:ZZ(1)}}, (2, 2), ZZ)
- # This time the row is there but column is empty
- A.setitem(0, 0, ZZ(0))
- assert A == SDM({0:{1:ZZ(1)}}, (2, 2), ZZ)
- raises(IndexError, lambda: A.setitem(2, 0, ZZ(1)))
- raises(IndexError, lambda: A.setitem(0, 2, ZZ(1)))
- def test_SDM_extract_slice():
- A = SDM({0:{0:ZZ(1), 1:ZZ(2)}, 1:{0:ZZ(3), 1:ZZ(4)}}, (2, 2), ZZ)
- B = A.extract_slice(slice(1, 2), slice(1, 2))
- assert B == SDM({0:{0:ZZ(4)}}, (1, 1), ZZ)
- def test_SDM_extract():
- A = SDM({0:{0:ZZ(1), 1:ZZ(2)}, 1:{0:ZZ(3), 1:ZZ(4)}}, (2, 2), ZZ)
- B = A.extract([1], [1])
- assert B == SDM({0:{0:ZZ(4)}}, (1, 1), ZZ)
- B = A.extract([1, 0], [1, 0])
- assert B == SDM({0:{0:ZZ(4), 1:ZZ(3)}, 1:{0:ZZ(2), 1:ZZ(1)}}, (2, 2), ZZ)
- B = A.extract([1, 1], [1, 1])
- assert B == SDM({0:{0:ZZ(4), 1:ZZ(4)}, 1:{0:ZZ(4), 1:ZZ(4)}}, (2, 2), ZZ)
- B = A.extract([-1], [-1])
- assert B == SDM({0:{0:ZZ(4)}}, (1, 1), ZZ)
- A = SDM({}, (2, 2), ZZ)
- B = A.extract([0, 1, 0], [0, 0])
- assert B == SDM({}, (3, 2), ZZ)
- A = SDM({0:{0:ZZ(1), 1:ZZ(2)}, 1:{0:ZZ(3), 1:ZZ(4)}}, (2, 2), ZZ)
- assert A.extract([], []) == SDM.zeros((0, 0), ZZ)
- assert A.extract([1], []) == SDM.zeros((1, 0), ZZ)
- assert A.extract([], [1]) == SDM.zeros((0, 1), ZZ)
- raises(IndexError, lambda: A.extract([2], [0]))
- raises(IndexError, lambda: A.extract([0], [2]))
- raises(IndexError, lambda: A.extract([-3], [0]))
- raises(IndexError, lambda: A.extract([0], [-3]))
- def test_SDM_zeros():
- A = SDM.zeros((2, 2), ZZ)
- assert A.domain == ZZ
- assert A.shape == (2, 2)
- assert dict(A) == {}
- def test_SDM_ones():
- A = SDM.ones((1, 2), QQ)
- assert A.domain == QQ
- assert A.shape == (1, 2)
- assert dict(A) == {0:{0:QQ(1), 1:QQ(1)}}
- def test_SDM_eye():
- A = SDM.eye((2, 2), ZZ)
- assert A.domain == ZZ
- assert A.shape == (2, 2)
- assert dict(A) == {0:{0:ZZ(1)}, 1:{1:ZZ(1)}}
- def test_SDM_diag():
- A = SDM.diag([ZZ(1), ZZ(2)], ZZ, (2, 3))
- assert A == SDM({0:{0:ZZ(1)}, 1:{1:ZZ(2)}}, (2, 3), ZZ)
- def test_SDM_transpose():
- A = SDM({0:{0:ZZ(1), 1:ZZ(2)}, 1:{0:ZZ(3), 1:ZZ(4)}}, (2, 2), ZZ)
- B = SDM({0:{0:ZZ(1), 1:ZZ(3)}, 1:{0:ZZ(2), 1:ZZ(4)}}, (2, 2), ZZ)
- assert A.transpose() == B
- A = SDM({0:{1:ZZ(2)}}, (2, 2), ZZ)
- B = SDM({1:{0:ZZ(2)}}, (2, 2), ZZ)
- assert A.transpose() == B
- A = SDM({0:{1:ZZ(2)}}, (1, 2), ZZ)
- B = SDM({1:{0:ZZ(2)}}, (2, 1), ZZ)
- assert A.transpose() == B
- def test_SDM_mul():
- A = SDM({0:{0:ZZ(2)}}, (2, 2), ZZ)
- B = SDM({0:{0:ZZ(4)}}, (2, 2), ZZ)
- assert A*ZZ(2) == B
- assert ZZ(2)*A == B
- raises(TypeError, lambda: A*QQ(1, 2))
- raises(TypeError, lambda: QQ(1, 2)*A)
- def test_SDM_mul_elementwise():
- A = SDM({0:{0:ZZ(2), 1:ZZ(2)}}, (2, 2), ZZ)
- B = SDM({0:{0:ZZ(4)}, 1:{0:ZZ(3)}}, (2, 2), ZZ)
- C = SDM({0:{0:ZZ(8)}}, (2, 2), ZZ)
- assert A.mul_elementwise(B) == C
- assert B.mul_elementwise(A) == C
- Aq = A.convert_to(QQ)
- A1 = SDM({0:{0:ZZ(1)}}, (1, 1), ZZ)
- raises(DMDomainError, lambda: Aq.mul_elementwise(B))
- raises(DMShapeError, lambda: A1.mul_elementwise(B))
- def test_SDM_matmul():
- A = SDM({0:{0:ZZ(2)}}, (2, 2), ZZ)
- B = SDM({0:{0:ZZ(4)}}, (2, 2), ZZ)
- assert A.matmul(A) == A*A == B
- C = SDM({0:{0:ZZ(2)}}, (2, 2), QQ)
- raises(DMDomainError, lambda: A.matmul(C))
- A = SDM({0:{0:ZZ(1), 1:ZZ(2)}, 1:{0:ZZ(3), 1:ZZ(4)}}, (2, 2), ZZ)
- B = SDM({0:{0:ZZ(7), 1:ZZ(10)}, 1:{0:ZZ(15), 1:ZZ(22)}}, (2, 2), ZZ)
- assert A.matmul(A) == A*A == B
- A22 = SDM({0:{0:ZZ(4)}}, (2, 2), ZZ)
- A32 = SDM({0:{0:ZZ(2)}}, (3, 2), ZZ)
- A23 = SDM({0:{0:ZZ(4)}}, (2, 3), ZZ)
- A33 = SDM({0:{0:ZZ(8)}}, (3, 3), ZZ)
- A22 = SDM({0:{0:ZZ(8)}}, (2, 2), ZZ)
- assert A32.matmul(A23) == A33
- assert A23.matmul(A32) == A22
- # XXX: @ not supported by SDM...
- #assert A32.matmul(A23) == A32 @ A23 == A33
- #assert A23.matmul(A32) == A23 @ A32 == A22
- #raises(DMShapeError, lambda: A23 @ A22)
- raises(DMShapeError, lambda: A23.matmul(A22))
- A = SDM({0: {0: ZZ(-1), 1: ZZ(1)}}, (1, 2), ZZ)
- B = SDM({0: {0: ZZ(-1)}, 1: {0: ZZ(-1)}}, (2, 1), ZZ)
- assert A.matmul(B) == A*B == SDM({}, (1, 1), ZZ)
- def test_matmul_exraw():
- def dm(d):
- result = {}
- for i, row in d.items():
- row = {j:val for j, val in row.items() if val}
- if row:
- result[i] = row
- return SDM(result, (2, 2), EXRAW)
- values = [S.NegativeInfinity, S.NegativeOne, S.Zero, S.One, S.Infinity]
- for a, b, c, d in product(*[values]*4):
- Ad = dm({0: {0:a, 1:b}, 1: {0:c, 1:d}})
- Ad2 = dm({0: {0:a*a + b*c, 1:a*b + b*d}, 1:{0:c*a + d*c, 1: c*b + d*d}})
- assert Ad * Ad == Ad2
- def test_SDM_add():
- A = SDM({0:{1:ZZ(1)}, 1:{0:ZZ(2), 1:ZZ(3)}}, (2, 2), ZZ)
- B = SDM({0:{0:ZZ(1)}, 1:{0:ZZ(-2), 1:ZZ(3)}}, (2, 2), ZZ)
- C = SDM({0:{0:ZZ(1), 1:ZZ(1)}, 1:{1:ZZ(6)}}, (2, 2), ZZ)
- assert A.add(B) == B.add(A) == A + B == B + A == C
- A = SDM({0:{1:ZZ(1)}}, (2, 2), ZZ)
- B = SDM({0:{0:ZZ(1)}, 1:{0:ZZ(-2), 1:ZZ(3)}}, (2, 2), ZZ)
- C = SDM({0:{0:ZZ(1), 1:ZZ(1)}, 1:{0:ZZ(-2), 1:ZZ(3)}}, (2, 2), ZZ)
- assert A.add(B) == B.add(A) == A + B == B + A == C
- raises(TypeError, lambda: A + [])
- def test_SDM_sub():
- A = SDM({0:{1:ZZ(1)}, 1:{0:ZZ(2), 1:ZZ(3)}}, (2, 2), ZZ)
- B = SDM({0:{0:ZZ(1)}, 1:{0:ZZ(-2), 1:ZZ(3)}}, (2, 2), ZZ)
- C = SDM({0:{0:ZZ(-1), 1:ZZ(1)}, 1:{0:ZZ(4)}}, (2, 2), ZZ)
- assert A.sub(B) == A - B == C
- raises(TypeError, lambda: A - [])
- def test_SDM_neg():
- A = SDM({0:{1:ZZ(1)}, 1:{0:ZZ(2), 1:ZZ(3)}}, (2, 2), ZZ)
- B = SDM({0:{1:ZZ(-1)}, 1:{0:ZZ(-2), 1:ZZ(-3)}}, (2, 2), ZZ)
- assert A.neg() == -A == B
- def test_SDM_convert_to():
- A = SDM({0:{1:ZZ(1)}, 1:{0:ZZ(2), 1:ZZ(3)}}, (2, 2), ZZ)
- B = SDM({0:{1:QQ(1)}, 1:{0:QQ(2), 1:QQ(3)}}, (2, 2), QQ)
- C = A.convert_to(QQ)
- assert C == B
- assert C.domain == QQ
- D = A.convert_to(ZZ)
- assert D == A
- assert D.domain == ZZ
- def test_SDM_hstack():
- A = SDM({0:{1:ZZ(1)}}, (2, 2), ZZ)
- B = SDM({1:{1:ZZ(1)}}, (2, 2), ZZ)
- AA = SDM({0:{1:ZZ(1), 3:ZZ(1)}}, (2, 4), ZZ)
- AB = SDM({0:{1:ZZ(1)}, 1:{3:ZZ(1)}}, (2, 4), ZZ)
- assert SDM.hstack(A) == A
- assert SDM.hstack(A, A) == AA
- assert SDM.hstack(A, B) == AB
- def test_SDM_vstack():
- A = SDM({0:{1:ZZ(1)}}, (2, 2), ZZ)
- B = SDM({1:{1:ZZ(1)}}, (2, 2), ZZ)
- AA = SDM({0:{1:ZZ(1)}, 2:{1:ZZ(1)}}, (4, 2), ZZ)
- AB = SDM({0:{1:ZZ(1)}, 3:{1:ZZ(1)}}, (4, 2), ZZ)
- assert SDM.vstack(A) == A
- assert SDM.vstack(A, A) == AA
- assert SDM.vstack(A, B) == AB
- def test_SDM_applyfunc():
- A = SDM({0:{1:ZZ(1)}}, (2, 2), ZZ)
- B = SDM({0:{1:ZZ(2)}}, (2, 2), ZZ)
- assert A.applyfunc(lambda x: 2*x, ZZ) == B
- def test_SDM_inv():
- A = SDM({0:{0:QQ(1), 1:QQ(2)}, 1:{0:QQ(3), 1:QQ(4)}}, (2, 2), QQ)
- B = SDM({0:{0:QQ(-2), 1:QQ(1)}, 1:{0:QQ(3, 2), 1:QQ(-1, 2)}}, (2, 2), QQ)
- assert A.inv() == B
- def test_SDM_det():
- A = SDM({0:{0:QQ(1), 1:QQ(2)}, 1:{0:QQ(3), 1:QQ(4)}}, (2, 2), QQ)
- assert A.det() == QQ(-2)
- def test_SDM_lu():
- A = SDM({0:{0:QQ(1), 1:QQ(2)}, 1:{0:QQ(3), 1:QQ(4)}}, (2, 2), QQ)
- L = SDM({0:{0:QQ(1)}, 1:{0:QQ(3), 1:QQ(1)}}, (2, 2), QQ)
- #U = SDM({0:{0:QQ(1), 1:QQ(2)}, 1:{0:QQ(3), 1:QQ(-2)}}, (2, 2), QQ)
- #swaps = []
- # This doesn't quite work. U has some nonzero elements in the lower part.
- #assert A.lu() == (L, U, swaps)
- assert A.lu()[0] == L
- def test_SDM_lu_solve():
- A = SDM({0:{0:QQ(1), 1:QQ(2)}, 1:{0:QQ(3), 1:QQ(4)}}, (2, 2), QQ)
- b = SDM({0:{0:QQ(1)}, 1:{0:QQ(2)}}, (2, 1), QQ)
- x = SDM({1:{0:QQ(1, 2)}}, (2, 1), QQ)
- assert A.matmul(x) == b
- assert A.lu_solve(b) == x
- def test_SDM_charpoly():
- A = SDM({0:{0:ZZ(1), 1:ZZ(2)}, 1:{0:ZZ(3), 1:ZZ(4)}}, (2, 2), ZZ)
- assert A.charpoly() == [ZZ(1), ZZ(-5), ZZ(-2)]
- def test_SDM_nullspace():
- A = SDM({0:{0:QQ(1), 1:QQ(1)}}, (2, 2), QQ)
- assert A.nullspace()[0] == SDM({0:{0:QQ(-1), 1:QQ(1)}}, (1, 2), QQ)
- def test_SDM_rref():
- eye2 = SDM({0:{0:QQ(1)}, 1:{1:QQ(1)}}, (2, 2), QQ)
- A = SDM({0:{0:QQ(1), 1:QQ(2)}, 1:{0:QQ(3), 1:QQ(4)}}, (2, 2), QQ)
- assert A.rref() == (eye2, [0, 1])
- A = SDM({0:{0:QQ(1)}, 1:{0:QQ(3), 1:QQ(4)}}, (2, 2), QQ)
- assert A.rref() == (eye2, [0, 1])
- A = SDM({0:{1:QQ(2)}, 1:{0:QQ(3), 1:QQ(4)}}, (2, 2), QQ)
- assert A.rref() == (eye2, [0, 1])
- A = SDM({0:{0:QQ(1), 1:QQ(2), 2:QQ(3)},
- 1:{0:QQ(4), 1:QQ(5), 2:QQ(6)},
- 2:{0:QQ(7), 1:QQ(8), 2:QQ(9)} }, (3, 3), QQ)
- Arref = SDM({0:{0:QQ(1), 2:QQ(-1)}, 1:{1:QQ(1), 2:QQ(2)}}, (3, 3), QQ)
- assert A.rref() == (Arref, [0, 1])
- A = SDM({0:{0:QQ(1), 1:QQ(2), 3:QQ(1)},
- 1:{0:QQ(1), 1:QQ(1), 2:QQ(9)}}, (2, 4), QQ)
- Arref = SDM({0:{0:QQ(1), 2:QQ(18), 3:QQ(-1)},
- 1:{1:QQ(1), 2:QQ(-9), 3:QQ(1)}}, (2, 4), QQ)
- assert A.rref() == (Arref, [0, 1])
- A = SDM({0:{0:QQ(1), 1:QQ(1), 2:QQ(1)},
- 1:{0:QQ(1), 1:QQ(2), 2:QQ(2)}}, (2, 3), QQ)
- Arref = SDM(
- {0: {0: QQ(1,1)}, 1: {1: QQ(1,1), 2: QQ(1,1)}},
- (2, 3), QQ)
- assert A.rref() == (Arref, [0, 1])
- def test_SDM_particular():
- A = SDM({0:{0:QQ(1)}}, (2, 2), QQ)
- Apart = SDM.zeros((1, 2), QQ)
- assert A.particular() == Apart
- def test_SDM_is_zero_matrix():
- A = SDM({0: {0: QQ(1)}}, (2, 2), QQ)
- Azero = SDM.zeros((1, 2), QQ)
- assert A.is_zero_matrix() is False
- assert Azero.is_zero_matrix() is True
- def test_SDM_is_upper():
- A = SDM({0: {0: QQ(1), 1: QQ(2), 2: QQ(3), 3: QQ(4)},
- 1: {1: QQ(5), 2: QQ(6), 3: QQ(7)},
- 2: {2: QQ(8), 3: QQ(9)}}, (3, 4), QQ)
- B = SDM({0: {0: QQ(1), 1: QQ(2), 2: QQ(3), 3: QQ(4)},
- 1: {1: QQ(5), 2: QQ(6), 3: QQ(7)},
- 2: {1: QQ(7), 2: QQ(8), 3: QQ(9)}}, (3, 4), QQ)
- assert A.is_upper() is True
- assert B.is_upper() is False
- def test_SDM_is_lower():
- A = SDM({0: {0: QQ(1), 1: QQ(2), 2: QQ(3), 3: QQ(4)},
- 1: {1: QQ(5), 2: QQ(6), 3: QQ(7)},
- 2: {2: QQ(8), 3: QQ(9)}}, (3, 4), QQ
- ).transpose()
- B = SDM({0: {0: QQ(1), 1: QQ(2), 2: QQ(3), 3: QQ(4)},
- 1: {1: QQ(5), 2: QQ(6), 3: QQ(7)},
- 2: {1: QQ(7), 2: QQ(8), 3: QQ(9)}}, (3, 4), QQ
- ).transpose()
- assert A.is_lower() is True
- assert B.is_lower() is False
|