|
|
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 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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) |
|
|
|