Spaces:
Running
Running
from sympy.testing.pytest import raises | |
from sympy.polys import ZZ, QQ | |
from sympy.polys.matrices.ddm import DDM | |
from sympy.polys.matrices.dense import ( | |
ddm_transpose, | |
ddm_iadd, ddm_isub, ddm_ineg, ddm_imatmul, ddm_imul, ddm_irref, | |
ddm_idet, ddm_iinv, ddm_ilu, ddm_ilu_split, ddm_ilu_solve, ddm_berk) | |
from sympy.polys.matrices.exceptions import ( | |
DMDomainError, | |
DMNonInvertibleMatrixError, | |
DMNonSquareMatrixError, | |
DMShapeError, | |
) | |
def test_ddm_transpose(): | |
a = [[1, 2], [3, 4]] | |
assert ddm_transpose(a) == [[1, 3], [2, 4]] | |
def test_ddm_iadd(): | |
a = [[1, 2], [3, 4]] | |
b = [[5, 6], [7, 8]] | |
ddm_iadd(a, b) | |
assert a == [[6, 8], [10, 12]] | |
def test_ddm_isub(): | |
a = [[1, 2], [3, 4]] | |
b = [[5, 6], [7, 8]] | |
ddm_isub(a, b) | |
assert a == [[-4, -4], [-4, -4]] | |
def test_ddm_ineg(): | |
a = [[1, 2], [3, 4]] | |
ddm_ineg(a) | |
assert a == [[-1, -2], [-3, -4]] | |
def test_ddm_matmul(): | |
a = [[1, 2], [3, 4]] | |
ddm_imul(a, 2) | |
assert a == [[2, 4], [6, 8]] | |
a = [[1, 2], [3, 4]] | |
ddm_imul(a, 0) | |
assert a == [[0, 0], [0, 0]] | |
def test_ddm_imatmul(): | |
a = [[1, 2, 3], [4, 5, 6]] | |
b = [[1, 2], [3, 4], [5, 6]] | |
c1 = [[0, 0], [0, 0]] | |
ddm_imatmul(c1, a, b) | |
assert c1 == [[22, 28], [49, 64]] | |
c2 = [[0, 0, 0], [0, 0, 0], [0, 0, 0]] | |
ddm_imatmul(c2, b, a) | |
assert c2 == [[9, 12, 15], [19, 26, 33], [29, 40, 51]] | |
b3 = [[1], [2], [3]] | |
c3 = [[0], [0]] | |
ddm_imatmul(c3, a, b3) | |
assert c3 == [[14], [32]] | |
def test_ddm_irref(): | |
# Empty matrix | |
A = [] | |
Ar = [] | |
pivots = [] | |
assert ddm_irref(A) == pivots | |
assert A == Ar | |
# Standard square case | |
A = [[QQ(0), QQ(1)], [QQ(1), QQ(1)]] | |
Ar = [[QQ(1), QQ(0)], [QQ(0), QQ(1)]] | |
pivots = [0, 1] | |
assert ddm_irref(A) == pivots | |
assert A == Ar | |
# m < n case | |
A = [[QQ(1), QQ(2), QQ(1)], [QQ(3), QQ(4), QQ(1)]] | |
Ar = [[QQ(1), QQ(0), QQ(-1)], [QQ(0), QQ(1), QQ(1)]] | |
pivots = [0, 1] | |
assert ddm_irref(A) == pivots | |
assert A == Ar | |
# same m < n but reversed | |
A = [[QQ(3), QQ(4), QQ(1)], [QQ(1), QQ(2), QQ(1)]] | |
Ar = [[QQ(1), QQ(0), QQ(-1)], [QQ(0), QQ(1), QQ(1)]] | |
pivots = [0, 1] | |
assert ddm_irref(A) == pivots | |
assert A == Ar | |
# m > n case | |
A = [[QQ(1), QQ(0)], [QQ(1), QQ(3)], [QQ(0), QQ(1)]] | |
Ar = [[QQ(1), QQ(0)], [QQ(0), QQ(1)], [QQ(0), QQ(0)]] | |
pivots = [0, 1] | |
assert ddm_irref(A) == pivots | |
assert A == Ar | |
# Example with missing pivot | |
A = [[QQ(1), QQ(0), QQ(1)], [QQ(3), QQ(0), QQ(1)]] | |
Ar = [[QQ(1), QQ(0), QQ(0)], [QQ(0), QQ(0), QQ(1)]] | |
pivots = [0, 2] | |
assert ddm_irref(A) == pivots | |
assert A == Ar | |
# Example with missing pivot and no replacement | |
A = [[QQ(0), QQ(1)], [QQ(0), QQ(2)], [QQ(1), QQ(0)]] | |
Ar = [[QQ(1), QQ(0)], [QQ(0), QQ(1)], [QQ(0), QQ(0)]] | |
pivots = [0, 1] | |
assert ddm_irref(A) == pivots | |
assert A == Ar | |
def test_ddm_idet(): | |
A = [] | |
assert ddm_idet(A, ZZ) == ZZ(1) | |
A = [[ZZ(2)]] | |
assert ddm_idet(A, ZZ) == ZZ(2) | |
A = [[ZZ(1), ZZ(2)], [ZZ(3), ZZ(4)]] | |
assert ddm_idet(A, ZZ) == ZZ(-2) | |
A = [[ZZ(1), ZZ(2), ZZ(3)], [ZZ(1), ZZ(2), ZZ(4)], [ZZ(1), ZZ(3), ZZ(5)]] | |
assert ddm_idet(A, ZZ) == ZZ(-1) | |
A = [[ZZ(1), ZZ(2), ZZ(3)], [ZZ(1), ZZ(2), ZZ(4)], [ZZ(1), ZZ(2), ZZ(5)]] | |
assert ddm_idet(A, ZZ) == ZZ(0) | |
A = [[QQ(1, 2), QQ(1, 2)], [QQ(1, 3), QQ(1, 4)]] | |
assert ddm_idet(A, QQ) == QQ(-1, 24) | |
def test_ddm_inv(): | |
A = [] | |
Ainv = [] | |
ddm_iinv(Ainv, A, QQ) | |
assert Ainv == A | |
A = [] | |
Ainv = [] | |
raises(DMDomainError, lambda: ddm_iinv(Ainv, A, ZZ)) | |
A = [[QQ(1), QQ(2)]] | |
Ainv = [[QQ(0), QQ(0)]] | |
raises(DMNonSquareMatrixError, lambda: ddm_iinv(Ainv, A, QQ)) | |
A = [[QQ(1, 1), QQ(2, 1)], [QQ(3, 1), QQ(4, 1)]] | |
Ainv = [[QQ(0), QQ(0)], [QQ(0), QQ(0)]] | |
Ainv_expected = [[QQ(-2, 1), QQ(1, 1)], [QQ(3, 2), QQ(-1, 2)]] | |
ddm_iinv(Ainv, A, QQ) | |
assert Ainv == Ainv_expected | |
A = [[QQ(1, 1), QQ(2, 1)], [QQ(2, 1), QQ(4, 1)]] | |
Ainv = [[QQ(0), QQ(0)], [QQ(0), QQ(0)]] | |
raises(DMNonInvertibleMatrixError, lambda: ddm_iinv(Ainv, A, QQ)) | |
def test_ddm_ilu(): | |
A = [] | |
Alu = [] | |
swaps = ddm_ilu(A) | |
assert A == Alu | |
assert swaps == [] | |
A = [[]] | |
Alu = [[]] | |
swaps = ddm_ilu(A) | |
assert A == Alu | |
assert swaps == [] | |
A = [[QQ(1), QQ(2)], [QQ(3), QQ(4)]] | |
Alu = [[QQ(1), QQ(2)], [QQ(3), QQ(-2)]] | |
swaps = ddm_ilu(A) | |
assert A == Alu | |
assert swaps == [] | |
A = [[QQ(0), QQ(2)], [QQ(3), QQ(4)]] | |
Alu = [[QQ(3), QQ(4)], [QQ(0), QQ(2)]] | |
swaps = ddm_ilu(A) | |
assert A == Alu | |
assert swaps == [(0, 1)] | |
A = [[QQ(1), QQ(2), QQ(3)], [QQ(4), QQ(5), QQ(6)], [QQ(7), QQ(8), QQ(9)]] | |
Alu = [[QQ(1), QQ(2), QQ(3)], [QQ(4), QQ(-3), QQ(-6)], [QQ(7), QQ(2), QQ(0)]] | |
swaps = ddm_ilu(A) | |
assert A == Alu | |
assert swaps == [] | |
A = [[QQ(0), QQ(1), QQ(2)], [QQ(0), QQ(1), QQ(3)], [QQ(1), QQ(1), QQ(2)]] | |
Alu = [[QQ(1), QQ(1), QQ(2)], [QQ(0), QQ(1), QQ(3)], [QQ(0), QQ(1), QQ(-1)]] | |
swaps = ddm_ilu(A) | |
assert A == Alu | |
assert swaps == [(0, 2)] | |
A = [[QQ(1), QQ(2), QQ(3)], [QQ(4), QQ(5), QQ(6)]] | |
Alu = [[QQ(1), QQ(2), QQ(3)], [QQ(4), QQ(-3), QQ(-6)]] | |
swaps = ddm_ilu(A) | |
assert A == Alu | |
assert swaps == [] | |
A = [[QQ(1), QQ(2)], [QQ(3), QQ(4)], [QQ(5), QQ(6)]] | |
Alu = [[QQ(1), QQ(2)], [QQ(3), QQ(-2)], [QQ(5), QQ(2)]] | |
swaps = ddm_ilu(A) | |
assert A == Alu | |
assert swaps == [] | |
def test_ddm_ilu_split(): | |
U = [] | |
L = [] | |
Uexp = [] | |
Lexp = [] | |
swaps = ddm_ilu_split(L, U, QQ) | |
assert U == Uexp | |
assert L == Lexp | |
assert swaps == [] | |
U = [[]] | |
L = [[QQ(1)]] | |
Uexp = [[]] | |
Lexp = [[QQ(1)]] | |
swaps = ddm_ilu_split(L, U, QQ) | |
assert U == Uexp | |
assert L == Lexp | |
assert swaps == [] | |
U = [[QQ(1), QQ(2)], [QQ(3), QQ(4)]] | |
L = [[QQ(1), QQ(0)], [QQ(0), QQ(1)]] | |
Uexp = [[QQ(1), QQ(2)], [QQ(0), QQ(-2)]] | |
Lexp = [[QQ(1), QQ(0)], [QQ(3), QQ(1)]] | |
swaps = ddm_ilu_split(L, U, QQ) | |
assert U == Uexp | |
assert L == Lexp | |
assert swaps == [] | |
U = [[QQ(1), QQ(2), QQ(3)], [QQ(4), QQ(5), QQ(6)]] | |
L = [[QQ(1), QQ(0)], [QQ(0), QQ(1)]] | |
Uexp = [[QQ(1), QQ(2), QQ(3)], [QQ(0), QQ(-3), QQ(-6)]] | |
Lexp = [[QQ(1), QQ(0)], [QQ(4), QQ(1)]] | |
swaps = ddm_ilu_split(L, U, QQ) | |
assert U == Uexp | |
assert L == Lexp | |
assert swaps == [] | |
U = [[QQ(1), QQ(2)], [QQ(3), QQ(4)], [QQ(5), QQ(6)]] | |
L = [[QQ(1), QQ(0), QQ(0)], [QQ(0), QQ(1), QQ(0)], [QQ(0), QQ(0), QQ(1)]] | |
Uexp = [[QQ(1), QQ(2)], [QQ(0), QQ(-2)], [QQ(0), QQ(0)]] | |
Lexp = [[QQ(1), QQ(0), QQ(0)], [QQ(3), QQ(1), QQ(0)], [QQ(5), QQ(2), QQ(1)]] | |
swaps = ddm_ilu_split(L, U, QQ) | |
assert U == Uexp | |
assert L == Lexp | |
assert swaps == [] | |
def test_ddm_ilu_solve(): | |
# Basic example | |
# A = [[QQ(1), QQ(2)], [QQ(3), QQ(4)]] | |
U = [[QQ(1), QQ(2)], [QQ(0), QQ(-2)]] | |
L = [[QQ(1), QQ(0)], [QQ(3), QQ(1)]] | |
swaps = [] | |
b = DDM([[QQ(1)], [QQ(2)]], (2, 1), QQ) | |
x = DDM([[QQ(0)], [QQ(0)]], (2, 1), QQ) | |
xexp = DDM([[QQ(0)], [QQ(1, 2)]], (2, 1), QQ) | |
ddm_ilu_solve(x, L, U, swaps, b) | |
assert x == xexp | |
# Example with swaps | |
# A = [[QQ(0), QQ(2)], [QQ(3), QQ(4)]] | |
U = [[QQ(3), QQ(4)], [QQ(0), QQ(2)]] | |
L = [[QQ(1), QQ(0)], [QQ(0), QQ(1)]] | |
swaps = [(0, 1)] | |
b = DDM([[QQ(1)], [QQ(2)]], (2, 1), QQ) | |
x = DDM([[QQ(0)], [QQ(0)]], (2, 1), QQ) | |
xexp = DDM([[QQ(0)], [QQ(1, 2)]], (2, 1), QQ) | |
ddm_ilu_solve(x, L, U, swaps, b) | |
assert x == xexp | |
# Overdetermined, consistent | |
# A = DDM([[QQ(1), QQ(2)], [QQ(3), QQ(4)], [QQ(5), QQ(6)]], (3, 2), QQ) | |
U = [[QQ(1), QQ(2)], [QQ(0), QQ(-2)], [QQ(0), QQ(0)]] | |
L = [[QQ(1), QQ(0), QQ(0)], [QQ(3), QQ(1), QQ(0)], [QQ(5), QQ(2), QQ(1)]] | |
swaps = [] | |
b = DDM([[QQ(1)], [QQ(2)], [QQ(3)]], (3, 1), QQ) | |
x = DDM([[QQ(0)], [QQ(0)]], (2, 1), QQ) | |
xexp = DDM([[QQ(0)], [QQ(1, 2)]], (2, 1), QQ) | |
ddm_ilu_solve(x, L, U, swaps, b) | |
assert x == xexp | |
# Overdetermined, inconsistent | |
b = DDM([[QQ(1)], [QQ(2)], [QQ(4)]], (3, 1), QQ) | |
raises(DMNonInvertibleMatrixError, lambda: ddm_ilu_solve(x, L, U, swaps, b)) | |
# Square, noninvertible | |
# A = DDM([[QQ(1), QQ(2)], [QQ(1), QQ(2)]], (2, 2), QQ) | |
U = [[QQ(1), QQ(2)], [QQ(0), QQ(0)]] | |
L = [[QQ(1), QQ(0)], [QQ(1), QQ(1)]] | |
swaps = [] | |
b = DDM([[QQ(1)], [QQ(2)]], (2, 1), QQ) | |
raises(DMNonInvertibleMatrixError, lambda: ddm_ilu_solve(x, L, U, swaps, b)) | |
# Underdetermined | |
# A = DDM([[QQ(1), QQ(2)]], (1, 2), QQ) | |
U = [[QQ(1), QQ(2)]] | |
L = [[QQ(1)]] | |
swaps = [] | |
b = DDM([[QQ(3)]], (1, 1), QQ) | |
raises(NotImplementedError, lambda: ddm_ilu_solve(x, L, U, swaps, b)) | |
# Shape mismatch | |
b3 = DDM([[QQ(1)], [QQ(2)], [QQ(3)]], (3, 1), QQ) | |
raises(DMShapeError, lambda: ddm_ilu_solve(x, L, U, swaps, b3)) | |
# Empty shape mismatch | |
U = [[QQ(1)]] | |
L = [[QQ(1)]] | |
swaps = [] | |
x = [[QQ(1)]] | |
b = [] | |
raises(DMShapeError, lambda: ddm_ilu_solve(x, L, U, swaps, b)) | |
# Empty system | |
U = [] | |
L = [] | |
swaps = [] | |
b = [] | |
x = [] | |
ddm_ilu_solve(x, L, U, swaps, b) | |
assert x == [] | |
def test_ddm_charpoly(): | |
A = [] | |
assert ddm_berk(A, ZZ) == [[ZZ(1)]] | |
A = [[ZZ(1), ZZ(2), ZZ(3)], [ZZ(4), ZZ(5), ZZ(6)], [ZZ(7), ZZ(8), ZZ(9)]] | |
Avec = [[ZZ(1)], [ZZ(-15)], [ZZ(-18)], [ZZ(0)]] | |
assert ddm_berk(A, ZZ) == Avec | |
A = DDM([[ZZ(1), ZZ(2)]], (1, 2), ZZ) | |
raises(DMShapeError, lambda: ddm_berk(A, ZZ)) | |