Kano001's picture
Upload 3077 files
6a86ad5 verified
raw
history blame
5.25 kB
from sympy import ZZ, Matrix
from sympy.polys.matrices import DM, DomainMatrix
from sympy.polys.matrices.dense import ddm_iinv
from sympy.polys.matrices.exceptions import DMNonInvertibleMatrixError
from sympy.matrices.exceptions import NonInvertibleMatrixError
import pytest
from sympy.testing.pytest import raises
from sympy.core.numbers import all_close
from sympy.abc import x
# Examples are given as adjugate matrix and determinant adj_det should match
# these exactly but inv_den only matches after cancel_denom.
INVERSE_EXAMPLES = [
(
'zz_1',
DomainMatrix([], (0, 0), ZZ),
DomainMatrix([], (0, 0), ZZ),
ZZ(1),
),
(
'zz_2',
DM([[2]], ZZ),
DM([[1]], ZZ),
ZZ(2),
),
(
'zz_3',
DM([[2, 0],
[0, 2]], ZZ),
DM([[2, 0],
[0, 2]], ZZ),
ZZ(4),
),
(
'zz_4',
DM([[1, 2],
[3, 4]], ZZ),
DM([[ 4, -2],
[-3, 1]], ZZ),
ZZ(-2),
),
(
'zz_5',
DM([[2, 2, 0],
[0, 2, 2],
[0, 0, 2]], ZZ),
DM([[4, -4, 4],
[0, 4, -4],
[0, 0, 4]], ZZ),
ZZ(8),
),
(
'zz_6',
DM([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]], ZZ),
DM([[-3, 6, -3],
[ 6, -12, 6],
[-3, 6, -3]], ZZ),
ZZ(0),
),
]
@pytest.mark.parametrize('name, A, A_inv, den', INVERSE_EXAMPLES)
def test_Matrix_inv(name, A, A_inv, den):
def _check(**kwargs):
if den != 0:
assert A.inv(**kwargs) == A_inv
else:
raises(NonInvertibleMatrixError, lambda: A.inv(**kwargs))
K = A.domain
A = A.to_Matrix()
A_inv = A_inv.to_Matrix() / K.to_sympy(den)
_check()
for method in ['GE', 'LU', 'ADJ', 'CH', 'LDL', 'QR']:
_check(method=method)
@pytest.mark.parametrize('name, A, A_inv, den', INVERSE_EXAMPLES)
def test_dm_inv_den(name, A, A_inv, den):
if den != 0:
A_inv_f, den_f = A.inv_den()
assert A_inv_f.cancel_denom(den_f) == A_inv.cancel_denom(den)
else:
raises(DMNonInvertibleMatrixError, lambda: A.inv_den())
@pytest.mark.parametrize('name, A, A_inv, den', INVERSE_EXAMPLES)
def test_dm_inv(name, A, A_inv, den):
A = A.to_field()
if den != 0:
A_inv = A_inv.to_field() / den
assert A.inv() == A_inv
else:
raises(DMNonInvertibleMatrixError, lambda: A.inv())
@pytest.mark.parametrize('name, A, A_inv, den', INVERSE_EXAMPLES)
def test_ddm_inv(name, A, A_inv, den):
A = A.to_field().to_ddm()
if den != 0:
A_inv = (A_inv.to_field() / den).to_ddm()
assert A.inv() == A_inv
else:
raises(DMNonInvertibleMatrixError, lambda: A.inv())
@pytest.mark.parametrize('name, A, A_inv, den', INVERSE_EXAMPLES)
def test_sdm_inv(name, A, A_inv, den):
A = A.to_field().to_sdm()
if den != 0:
A_inv = (A_inv.to_field() / den).to_sdm()
assert A.inv() == A_inv
else:
raises(DMNonInvertibleMatrixError, lambda: A.inv())
@pytest.mark.parametrize('name, A, A_inv, den', INVERSE_EXAMPLES)
def test_dense_ddm_iinv(name, A, A_inv, den):
A = A.to_field().to_ddm().copy()
K = A.domain
A_result = A.copy()
if den != 0:
A_inv = (A_inv.to_field() / den).to_ddm()
ddm_iinv(A_result, A, K)
assert A_result == A_inv
else:
raises(DMNonInvertibleMatrixError, lambda: ddm_iinv(A_result, A, K))
@pytest.mark.parametrize('name, A, A_inv, den', INVERSE_EXAMPLES)
def test_Matrix_adjugate(name, A, A_inv, den):
A = A.to_Matrix()
A_inv = A_inv.to_Matrix()
assert A.adjugate() == A_inv
for method in ["bareiss", "berkowitz", "bird", "laplace", "lu"]:
assert A.adjugate(method=method) == A_inv
@pytest.mark.parametrize('name, A, A_inv, den', INVERSE_EXAMPLES)
def test_dm_adj_det(name, A, A_inv, den):
assert A.adj_det() == (A_inv, den)
def test_inverse_inexact():
M = Matrix([[x-0.3, -0.06, -0.22],
[-0.46, x-0.48, -0.41],
[-0.14, -0.39, x-0.64]])
Mn = Matrix([[1.0*x**2 - 1.12*x + 0.1473, 0.06*x + 0.0474, 0.22*x - 0.081],
[0.46*x - 0.237, 1.0*x**2 - 0.94*x + 0.1612, 0.41*x - 0.0218],
[0.14*x + 0.1122, 0.39*x - 0.1086, 1.0*x**2 - 0.78*x + 0.1164]])
d = 1.0*x**3 - 1.42*x**2 + 0.4249*x - 0.0546540000000002
Mi = Mn / d
M_dm = M.to_DM()
M_dmd = M_dm.to_dense()
M_dm_num, M_dm_den = M_dm.inv_den()
M_dmd_num, M_dmd_den = M_dmd.inv_den()
# XXX: We don't check M_dm().to_field().inv() which currently uses division
# and produces a more complicate result from gcd cancellation failing.
# DomainMatrix.inv() over RR(x) should be changed to clear denominators and
# use DomainMatrix.inv_den().
Minvs = [
M.inv(),
(M_dm_num.to_field() / M_dm_den).to_Matrix(),
(M_dmd_num.to_field() / M_dmd_den).to_Matrix(),
M_dm_num.to_Matrix() / M_dm_den.as_expr(),
M_dmd_num.to_Matrix() / M_dmd_den.as_expr(),
]
for Minv in Minvs:
for Mi1, Mi2 in zip(Minv.flat(), Mi.flat()):
assert all_close(Mi2, Mi1)