346 lines
9.3 KiB
Python
346 lines
9.3 KiB
Python
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 (
|
|
DMShapeError, DMNonInvertibleMatrixError, DMNonSquareMatrixError)
|
|
|
|
|
|
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(ValueError, 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))
|