# # Code for testing deprecated matrix classes. New test code should not be added # here. Instead, add it to test_matrixbase.py. # # This entire test module and the corresponding sympy/matrices/common.py # module will be removed in a future release. # from sympy.testing.pytest import raises, XFAIL, warns_deprecated_sympy from sympy.assumptions import Q from sympy.core.expr import Expr from sympy.core.add import Add from sympy.core.function import Function from sympy.core.kind import NumberKind, UndefinedKind from sympy.core.numbers import I, Integer, oo, pi, Rational from sympy.core.singleton import S from sympy.core.symbol import Symbol, symbols from sympy.functions.elementary.complexes import Abs from sympy.functions.elementary.exponential import exp from sympy.functions.elementary.miscellaneous import sqrt from sympy.functions.elementary.trigonometric import cos, sin from sympy.matrices.exceptions import ShapeError, NonSquareMatrixError from sympy.matrices.kind import MatrixKind from sympy.matrices.common import ( _MinimalMatrix, _CastableMatrix, MatrixShaping, MatrixProperties, MatrixOperations, MatrixArithmetic, MatrixSpecial) from sympy.matrices.matrices import MatrixCalculus from sympy.matrices import (Matrix, diag, eye, matrix_multiply_elementwise, ones, zeros, SparseMatrix, banded, MutableDenseMatrix, MutableSparseMatrix, ImmutableDenseMatrix, ImmutableSparseMatrix) from sympy.polys.polytools import Poly from sympy.utilities.iterables import flatten from sympy.tensor.array.dense_ndim_array import ImmutableDenseNDimArray as Array from sympy.abc import x, y, z def test_matrix_deprecated_isinstance(): # Test that e.g. isinstance(M, MatrixCommon) still gives True when M is a # Matrix for each of the deprecated matrix classes. from sympy.matrices.common import ( MatrixRequired, MatrixShaping, MatrixSpecial, MatrixProperties, MatrixOperations, MatrixArithmetic, MatrixCommon ) from sympy.matrices.matrices import ( MatrixDeterminant, MatrixReductions, MatrixSubspaces, MatrixEigen, MatrixCalculus, MatrixDeprecated ) from sympy import ( Matrix, ImmutableMatrix, SparseMatrix, ImmutableSparseMatrix ) all_mixins = ( MatrixRequired, MatrixShaping, MatrixSpecial, MatrixProperties, MatrixOperations, MatrixArithmetic, MatrixCommon, MatrixDeterminant, MatrixReductions, MatrixSubspaces, MatrixEigen, MatrixCalculus, MatrixDeprecated ) all_matrices = ( Matrix, ImmutableMatrix, SparseMatrix, ImmutableSparseMatrix ) Ms = [M([[1, 2], [3, 4]]) for M in all_matrices] t = () for mixin in all_mixins: for M in Ms: with warns_deprecated_sympy(): assert isinstance(M, mixin) is True with warns_deprecated_sympy(): assert isinstance(t, mixin) is False # classes to test the deprecated matrix classes. We use warns_deprecated_sympy # to suppress the deprecation warnings because subclassing the deprecated # classes causes a warning to be raised. with warns_deprecated_sympy(): class ShapingOnlyMatrix(_MinimalMatrix, _CastableMatrix, MatrixShaping): pass def eye_Shaping(n): return ShapingOnlyMatrix(n, n, lambda i, j: int(i == j)) def zeros_Shaping(n): return ShapingOnlyMatrix(n, n, lambda i, j: 0) with warns_deprecated_sympy(): class PropertiesOnlyMatrix(_MinimalMatrix, _CastableMatrix, MatrixProperties): pass def eye_Properties(n): return PropertiesOnlyMatrix(n, n, lambda i, j: int(i == j)) def zeros_Properties(n): return PropertiesOnlyMatrix(n, n, lambda i, j: 0) with warns_deprecated_sympy(): class OperationsOnlyMatrix(_MinimalMatrix, _CastableMatrix, MatrixOperations): pass def eye_Operations(n): return OperationsOnlyMatrix(n, n, lambda i, j: int(i == j)) def zeros_Operations(n): return OperationsOnlyMatrix(n, n, lambda i, j: 0) with warns_deprecated_sympy(): class ArithmeticOnlyMatrix(_MinimalMatrix, _CastableMatrix, MatrixArithmetic): pass def eye_Arithmetic(n): return ArithmeticOnlyMatrix(n, n, lambda i, j: int(i == j)) def zeros_Arithmetic(n): return ArithmeticOnlyMatrix(n, n, lambda i, j: 0) with warns_deprecated_sympy(): class SpecialOnlyMatrix(_MinimalMatrix, _CastableMatrix, MatrixSpecial): pass with warns_deprecated_sympy(): class CalculusOnlyMatrix(_MinimalMatrix, _CastableMatrix, MatrixCalculus): pass def test__MinimalMatrix(): x = _MinimalMatrix(2, 3, [1, 2, 3, 4, 5, 6]) assert x.rows == 2 assert x.cols == 3 assert x[2] == 3 assert x[1, 1] == 5 assert list(x) == [1, 2, 3, 4, 5, 6] assert list(x[1, :]) == [4, 5, 6] assert list(x[:, 1]) == [2, 5] assert list(x[:, :]) == list(x) assert x[:, :] == x assert _MinimalMatrix(x) == x assert _MinimalMatrix([[1, 2, 3], [4, 5, 6]]) == x assert _MinimalMatrix(([1, 2, 3], [4, 5, 6])) == x assert _MinimalMatrix([(1, 2, 3), (4, 5, 6)]) == x assert _MinimalMatrix(((1, 2, 3), (4, 5, 6))) == x assert not (_MinimalMatrix([[1, 2], [3, 4], [5, 6]]) == x) def test_kind(): assert Matrix([[1, 2], [3, 4]]).kind == MatrixKind(NumberKind) assert Matrix([[0, 0], [0, 0]]).kind == MatrixKind(NumberKind) assert Matrix(0, 0, []).kind == MatrixKind(NumberKind) assert Matrix([[x]]).kind == MatrixKind(NumberKind) assert Matrix([[1, Matrix([[1]])]]).kind == MatrixKind(UndefinedKind) assert SparseMatrix([[1]]).kind == MatrixKind(NumberKind) assert SparseMatrix([[1, Matrix([[1]])]]).kind == MatrixKind(UndefinedKind) # ShapingOnlyMatrix tests def test_vec(): m = ShapingOnlyMatrix(2, 2, [1, 3, 2, 4]) m_vec = m.vec() assert m_vec.cols == 1 for i in range(4): assert m_vec[i] == i + 1 def test_todok(): a, b, c, d = symbols('a:d') m1 = MutableDenseMatrix([[a, b], [c, d]]) m2 = ImmutableDenseMatrix([[a, b], [c, d]]) m3 = MutableSparseMatrix([[a, b], [c, d]]) m4 = ImmutableSparseMatrix([[a, b], [c, d]]) assert m1.todok() == m2.todok() == m3.todok() == m4.todok() == \ {(0, 0): a, (0, 1): b, (1, 0): c, (1, 1): d} def test_tolist(): lst = [[S.One, S.Half, x*y, S.Zero], [x, y, z, x**2], [y, -S.One, z*x, 3]] flat_lst = [S.One, S.Half, x*y, S.Zero, x, y, z, x**2, y, -S.One, z*x, 3] m = ShapingOnlyMatrix(3, 4, flat_lst) assert m.tolist() == lst def test_todod(): m = ShapingOnlyMatrix(3, 2, [[S.One, 0], [0, S.Half], [x, 0]]) dict = {0: {0: S.One}, 1: {1: S.Half}, 2: {0: x}} assert m.todod() == dict def test_row_col_del(): e = ShapingOnlyMatrix(3, 3, [1, 2, 3, 4, 5, 6, 7, 8, 9]) raises(IndexError, lambda: e.row_del(5)) raises(IndexError, lambda: e.row_del(-5)) raises(IndexError, lambda: e.col_del(5)) raises(IndexError, lambda: e.col_del(-5)) assert e.row_del(2) == e.row_del(-1) == Matrix([[1, 2, 3], [4, 5, 6]]) assert e.col_del(2) == e.col_del(-1) == Matrix([[1, 2], [4, 5], [7, 8]]) assert e.row_del(1) == e.row_del(-2) == Matrix([[1, 2, 3], [7, 8, 9]]) assert e.col_del(1) == e.col_del(-2) == Matrix([[1, 3], [4, 6], [7, 9]]) def test_get_diag_blocks1(): a = Matrix([[1, 2], [2, 3]]) b = Matrix([[3, x], [y, 3]]) c = Matrix([[3, x, 3], [y, 3, z], [x, y, z]]) assert a.get_diag_blocks() == [a] assert b.get_diag_blocks() == [b] assert c.get_diag_blocks() == [c] def test_get_diag_blocks2(): a = Matrix([[1, 2], [2, 3]]) b = Matrix([[3, x], [y, 3]]) c = Matrix([[3, x, 3], [y, 3, z], [x, y, z]]) A, B, C, D = diag(a, b, b), diag(a, b, c), diag(a, c, b), diag(c, c, b) A = ShapingOnlyMatrix(A.rows, A.cols, A) B = ShapingOnlyMatrix(B.rows, B.cols, B) C = ShapingOnlyMatrix(C.rows, C.cols, C) D = ShapingOnlyMatrix(D.rows, D.cols, D) assert A.get_diag_blocks() == [a, b, b] assert B.get_diag_blocks() == [a, b, c] assert C.get_diag_blocks() == [a, c, b] assert D.get_diag_blocks() == [c, c, b] def test_shape(): m = ShapingOnlyMatrix(1, 2, [0, 0]) assert m.shape == (1, 2) def test_reshape(): m0 = eye_Shaping(3) assert m0.reshape(1, 9) == Matrix(1, 9, (1, 0, 0, 0, 1, 0, 0, 0, 1)) m1 = ShapingOnlyMatrix(3, 4, lambda i, j: i + j) assert m1.reshape( 4, 3) == Matrix(((0, 1, 2), (3, 1, 2), (3, 4, 2), (3, 4, 5))) assert m1.reshape(2, 6) == Matrix(((0, 1, 2, 3, 1, 2), (3, 4, 2, 3, 4, 5))) def test_row_col(): m = ShapingOnlyMatrix(3, 3, [1, 2, 3, 4, 5, 6, 7, 8, 9]) assert m.row(0) == Matrix(1, 3, [1, 2, 3]) assert m.col(0) == Matrix(3, 1, [1, 4, 7]) def test_row_join(): assert eye_Shaping(3).row_join(Matrix([7, 7, 7])) == \ Matrix([[1, 0, 0, 7], [0, 1, 0, 7], [0, 0, 1, 7]]) def test_col_join(): assert eye_Shaping(3).col_join(Matrix([[7, 7, 7]])) == \ Matrix([[1, 0, 0], [0, 1, 0], [0, 0, 1], [7, 7, 7]]) def test_row_insert(): r4 = Matrix([[4, 4, 4]]) for i in range(-4, 5): l = [1, 0, 0] l.insert(i, 4) assert flatten(eye_Shaping(3).row_insert(i, r4).col(0).tolist()) == l def test_col_insert(): c4 = Matrix([4, 4, 4]) for i in range(-4, 5): l = [0, 0, 0] l.insert(i, 4) assert flatten(zeros_Shaping(3).col_insert(i, c4).row(0).tolist()) == l # issue 13643 assert eye_Shaping(6).col_insert(3, Matrix([[2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2]])) == \ Matrix([[1, 0, 0, 2, 2, 0, 0, 0], [0, 1, 0, 2, 2, 0, 0, 0], [0, 0, 1, 2, 2, 0, 0, 0], [0, 0, 0, 2, 2, 1, 0, 0], [0, 0, 0, 2, 2, 0, 1, 0], [0, 0, 0, 2, 2, 0, 0, 1]]) def test_extract(): m = ShapingOnlyMatrix(4, 3, lambda i, j: i*3 + j) assert m.extract([0, 1, 3], [0, 1]) == Matrix(3, 2, [0, 1, 3, 4, 9, 10]) assert m.extract([0, 3], [0, 0, 2]) == Matrix(2, 3, [0, 0, 2, 9, 9, 11]) assert m.extract(range(4), range(3)) == m raises(IndexError, lambda: m.extract([4], [0])) raises(IndexError, lambda: m.extract([0], [3])) def test_hstack(): m = ShapingOnlyMatrix(4, 3, lambda i, j: i*3 + j) m2 = ShapingOnlyMatrix(3, 4, lambda i, j: i*3 + j) assert m == m.hstack(m) assert m.hstack(m, m, m) == ShapingOnlyMatrix.hstack(m, m, m) == Matrix([ [0, 1, 2, 0, 1, 2, 0, 1, 2], [3, 4, 5, 3, 4, 5, 3, 4, 5], [6, 7, 8, 6, 7, 8, 6, 7, 8], [9, 10, 11, 9, 10, 11, 9, 10, 11]]) raises(ShapeError, lambda: m.hstack(m, m2)) assert Matrix.hstack() == Matrix() # test regression #12938 M1 = Matrix.zeros(0, 0) M2 = Matrix.zeros(0, 1) M3 = Matrix.zeros(0, 2) M4 = Matrix.zeros(0, 3) m = ShapingOnlyMatrix.hstack(M1, M2, M3, M4) assert m.rows == 0 and m.cols == 6 def test_vstack(): m = ShapingOnlyMatrix(4, 3, lambda i, j: i*3 + j) m2 = ShapingOnlyMatrix(3, 4, lambda i, j: i*3 + j) assert m == m.vstack(m) assert m.vstack(m, m, m) == ShapingOnlyMatrix.vstack(m, m, m) == Matrix([ [0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11], [0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11], [0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]]) raises(ShapeError, lambda: m.vstack(m, m2)) assert Matrix.vstack() == Matrix() # PropertiesOnlyMatrix tests def test_atoms(): m = PropertiesOnlyMatrix(2, 2, [1, 2, x, 1 - 1/x]) assert m.atoms() == {S.One, S(2), S.NegativeOne, x} assert m.atoms(Symbol) == {x} def test_free_symbols(): assert PropertiesOnlyMatrix([[x], [0]]).free_symbols == {x} def test_has(): A = PropertiesOnlyMatrix(((x, y), (2, 3))) assert A.has(x) assert not A.has(z) assert A.has(Symbol) A = PropertiesOnlyMatrix(((2, y), (2, 3))) assert not A.has(x) def test_is_anti_symmetric(): x = symbols('x') assert PropertiesOnlyMatrix(2, 1, [1, 2]).is_anti_symmetric() is False m = PropertiesOnlyMatrix(3, 3, [0, x**2 + 2*x + 1, y, -(x + 1)**2, 0, x*y, -y, -x*y, 0]) assert m.is_anti_symmetric() is True assert m.is_anti_symmetric(simplify=False) is False assert m.is_anti_symmetric(simplify=lambda x: x) is False m = PropertiesOnlyMatrix(3, 3, [x.expand() for x in m]) assert m.is_anti_symmetric(simplify=False) is True m = PropertiesOnlyMatrix(3, 3, [x.expand() for x in [S.One] + list(m)[1:]]) assert m.is_anti_symmetric() is False def test_diagonal_symmetrical(): m = PropertiesOnlyMatrix(2, 2, [0, 1, 1, 0]) assert not m.is_diagonal() assert m.is_symmetric() assert m.is_symmetric(simplify=False) m = PropertiesOnlyMatrix(2, 2, [1, 0, 0, 1]) assert m.is_diagonal() m = PropertiesOnlyMatrix(3, 3, diag(1, 2, 3)) assert m.is_diagonal() assert m.is_symmetric() m = PropertiesOnlyMatrix(3, 3, [1, 0, 0, 0, 2, 0, 0, 0, 3]) assert m == diag(1, 2, 3) m = PropertiesOnlyMatrix(2, 3, zeros(2, 3)) assert not m.is_symmetric() assert m.is_diagonal() m = PropertiesOnlyMatrix(((5, 0), (0, 6), (0, 0))) assert m.is_diagonal() m = PropertiesOnlyMatrix(((5, 0, 0), (0, 6, 0))) assert m.is_diagonal() m = Matrix(3, 3, [1, x**2 + 2*x + 1, y, (x + 1)**2, 2, 0, y, 0, 3]) assert m.is_symmetric() assert not m.is_symmetric(simplify=False) assert m.expand().is_symmetric(simplify=False) def test_is_hermitian(): a = PropertiesOnlyMatrix([[1, I], [-I, 1]]) assert a.is_hermitian a = PropertiesOnlyMatrix([[2*I, I], [-I, 1]]) assert a.is_hermitian is False a = PropertiesOnlyMatrix([[x, I], [-I, 1]]) assert a.is_hermitian is None a = PropertiesOnlyMatrix([[x, 1], [-I, 1]]) assert a.is_hermitian is False def test_is_Identity(): assert eye_Properties(3).is_Identity assert not PropertiesOnlyMatrix(zeros(3)).is_Identity assert not PropertiesOnlyMatrix(ones(3)).is_Identity # issue 6242 assert not PropertiesOnlyMatrix([[1, 0, 0]]).is_Identity def test_is_symbolic(): a = PropertiesOnlyMatrix([[x, x], [x, x]]) assert a.is_symbolic() is True a = PropertiesOnlyMatrix([[1, 2, 3, 4], [5, 6, 7, 8]]) assert a.is_symbolic() is False a = PropertiesOnlyMatrix([[1, 2, 3, 4], [5, 6, x, 8]]) assert a.is_symbolic() is True a = PropertiesOnlyMatrix([[1, x, 3]]) assert a.is_symbolic() is True a = PropertiesOnlyMatrix([[1, 2, 3]]) assert a.is_symbolic() is False a = PropertiesOnlyMatrix([[1], [x], [3]]) assert a.is_symbolic() is True a = PropertiesOnlyMatrix([[1], [2], [3]]) assert a.is_symbolic() is False def test_is_upper(): a = PropertiesOnlyMatrix([[1, 2, 3]]) assert a.is_upper is True a = PropertiesOnlyMatrix([[1], [2], [3]]) assert a.is_upper is False def test_is_lower(): a = PropertiesOnlyMatrix([[1, 2, 3]]) assert a.is_lower is False a = PropertiesOnlyMatrix([[1], [2], [3]]) assert a.is_lower is True def test_is_square(): m = PropertiesOnlyMatrix([[1], [1]]) m2 = PropertiesOnlyMatrix([[2, 2], [2, 2]]) assert not m.is_square assert m2.is_square def test_is_symmetric(): m = PropertiesOnlyMatrix(2, 2, [0, 1, 1, 0]) assert m.is_symmetric() m = PropertiesOnlyMatrix(2, 2, [0, 1, 0, 1]) assert not m.is_symmetric() def test_is_hessenberg(): A = PropertiesOnlyMatrix([[3, 4, 1], [2, 4, 5], [0, 1, 2]]) assert A.is_upper_hessenberg A = PropertiesOnlyMatrix(3, 3, [3, 2, 0, 4, 4, 1, 1, 5, 2]) assert A.is_lower_hessenberg A = PropertiesOnlyMatrix(3, 3, [3, 2, -1, 4, 4, 1, 1, 5, 2]) assert A.is_lower_hessenberg is False assert A.is_upper_hessenberg is False A = PropertiesOnlyMatrix([[3, 4, 1], [2, 4, 5], [3, 1, 2]]) assert not A.is_upper_hessenberg def test_is_zero(): assert PropertiesOnlyMatrix(0, 0, []).is_zero_matrix assert PropertiesOnlyMatrix([[0, 0], [0, 0]]).is_zero_matrix assert PropertiesOnlyMatrix(zeros(3, 4)).is_zero_matrix assert not PropertiesOnlyMatrix(eye(3)).is_zero_matrix assert PropertiesOnlyMatrix([[x, 0], [0, 0]]).is_zero_matrix == None assert PropertiesOnlyMatrix([[x, 1], [0, 0]]).is_zero_matrix == False a = Symbol('a', nonzero=True) assert PropertiesOnlyMatrix([[a, 0], [0, 0]]).is_zero_matrix == False def test_values(): assert set(PropertiesOnlyMatrix(2, 2, [0, 1, 2, 3] ).values()) == {1, 2, 3} x = Symbol('x', real=True) assert set(PropertiesOnlyMatrix(2, 2, [x, 0, 0, 1] ).values()) == {x, 1} # OperationsOnlyMatrix tests def test_applyfunc(): m0 = OperationsOnlyMatrix(eye(3)) assert m0.applyfunc(lambda x: 2*x) == eye(3)*2 assert m0.applyfunc(lambda x: 0) == zeros(3) assert m0.applyfunc(lambda x: 1) == ones(3) def test_adjoint(): dat = [[0, I], [1, 0]] ans = OperationsOnlyMatrix([[0, 1], [-I, 0]]) assert ans.adjoint() == Matrix(dat) def test_as_real_imag(): m1 = OperationsOnlyMatrix(2, 2, [1, 2, 3, 4]) m3 = OperationsOnlyMatrix(2, 2, [1 + S.ImaginaryUnit, 2 + 2*S.ImaginaryUnit, 3 + 3*S.ImaginaryUnit, 4 + 4*S.ImaginaryUnit]) a, b = m3.as_real_imag() assert a == m1 assert b == m1 def test_conjugate(): M = OperationsOnlyMatrix([[0, I, 5], [1, 2, 0]]) assert M.T == Matrix([[0, 1], [I, 2], [5, 0]]) assert M.C == Matrix([[0, -I, 5], [1, 2, 0]]) assert M.C == M.conjugate() assert M.H == M.T.C assert M.H == Matrix([[ 0, 1], [-I, 2], [ 5, 0]]) def test_doit(): a = OperationsOnlyMatrix([[Add(x, x, evaluate=False)]]) assert a[0] != 2*x assert a.doit() == Matrix([[2*x]]) def test_evalf(): a = OperationsOnlyMatrix(2, 1, [sqrt(5), 6]) assert all(a.evalf()[i] == a[i].evalf() for i in range(2)) assert all(a.evalf(2)[i] == a[i].evalf(2) for i in range(2)) assert all(a.n(2)[i] == a[i].n(2) for i in range(2)) def test_expand(): m0 = OperationsOnlyMatrix([[x*(x + y), 2], [((x + y)*y)*x, x*(y + x*(x + y))]]) # Test if expand() returns a matrix m1 = m0.expand() assert m1 == Matrix( [[x*y + x**2, 2], [x*y**2 + y*x**2, x*y + y*x**2 + x**3]]) a = Symbol('a', real=True) assert OperationsOnlyMatrix(1, 1, [exp(I*a)]).expand(complex=True) == \ Matrix([cos(a) + I*sin(a)]) def test_refine(): m0 = OperationsOnlyMatrix([[Abs(x)**2, sqrt(x**2)], [sqrt(x**2)*Abs(y)**2, sqrt(y**2)*Abs(x)**2]]) m1 = m0.refine(Q.real(x) & Q.real(y)) assert m1 == Matrix([[x**2, Abs(x)], [y**2*Abs(x), x**2*Abs(y)]]) m1 = m0.refine(Q.positive(x) & Q.positive(y)) assert m1 == Matrix([[x**2, x], [x*y**2, x**2*y]]) m1 = m0.refine(Q.negative(x) & Q.negative(y)) assert m1 == Matrix([[x**2, -x], [-x*y**2, -x**2*y]]) def test_replace(): F, G = symbols('F, G', cls=Function) K = OperationsOnlyMatrix(2, 2, lambda i, j: G(i+j)) M = OperationsOnlyMatrix(2, 2, lambda i, j: F(i+j)) N = M.replace(F, G) assert N == K def test_replace_map(): F, G = symbols('F, G', cls=Function) K = OperationsOnlyMatrix(2, 2, [(G(0), {F(0): G(0)}), (G(1), {F(1): G(1)}), (G(1), {F(1) \ : G(1)}), (G(2), {F(2): G(2)})]) M = OperationsOnlyMatrix(2, 2, lambda i, j: F(i+j)) N = M.replace(F, G, True) assert N == K def test_rot90(): A = Matrix([[1, 2], [3, 4]]) assert A == A.rot90(0) == A.rot90(4) assert A.rot90(2) == A.rot90(-2) == A.rot90(6) == Matrix(((4, 3), (2, 1))) assert A.rot90(3) == A.rot90(-1) == A.rot90(7) == Matrix(((2, 4), (1, 3))) assert A.rot90() == A.rot90(-7) == A.rot90(-3) == Matrix(((3, 1), (4, 2))) def test_simplify(): n = Symbol('n') f = Function('f') M = OperationsOnlyMatrix([[ 1/x + 1/y, (x + x*y) / x ], [ (f(x) + y*f(x))/f(x), 2 * (1/n - cos(n * pi)/n) / pi ]]) assert M.simplify() == Matrix([[ (x + y)/(x * y), 1 + y ], [ 1 + y, 2*((1 - 1*cos(pi*n))/(pi*n)) ]]) eq = (1 + x)**2 M = OperationsOnlyMatrix([[eq]]) assert M.simplify() == Matrix([[eq]]) assert M.simplify(ratio=oo) == Matrix([[eq.simplify(ratio=oo)]]) # https://github.com/sympy/sympy/issues/19353 m = Matrix([[30, 2], [3, 4]]) assert (1/(m.trace())).simplify() == Rational(1, 34) def test_subs(): assert OperationsOnlyMatrix([[1, x], [x, 4]]).subs(x, 5) == Matrix([[1, 5], [5, 4]]) assert OperationsOnlyMatrix([[x, 2], [x + y, 4]]).subs([[x, -1], [y, -2]]) == \ Matrix([[-1, 2], [-3, 4]]) assert OperationsOnlyMatrix([[x, 2], [x + y, 4]]).subs([(x, -1), (y, -2)]) == \ Matrix([[-1, 2], [-3, 4]]) assert OperationsOnlyMatrix([[x, 2], [x + y, 4]]).subs({x: -1, y: -2}) == \ Matrix([[-1, 2], [-3, 4]]) assert OperationsOnlyMatrix([[x*y]]).subs({x: y - 1, y: x - 1}, simultaneous=True) == \ Matrix([[(x - 1)*(y - 1)]]) def test_trace(): M = OperationsOnlyMatrix([[1, 0, 0], [0, 5, 0], [0, 0, 8]]) assert M.trace() == 14 def test_xreplace(): assert OperationsOnlyMatrix([[1, x], [x, 4]]).xreplace({x: 5}) == \ Matrix([[1, 5], [5, 4]]) assert OperationsOnlyMatrix([[x, 2], [x + y, 4]]).xreplace({x: -1, y: -2}) == \ Matrix([[-1, 2], [-3, 4]]) def test_permute(): a = OperationsOnlyMatrix(3, 4, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]) raises(IndexError, lambda: a.permute([[0, 5]])) raises(ValueError, lambda: a.permute(Symbol('x'))) b = a.permute_rows([[0, 2], [0, 1]]) assert a.permute([[0, 2], [0, 1]]) == b == Matrix([ [5, 6, 7, 8], [9, 10, 11, 12], [1, 2, 3, 4]]) b = a.permute_cols([[0, 2], [0, 1]]) assert a.permute([[0, 2], [0, 1]], orientation='cols') == b ==\ Matrix([ [ 2, 3, 1, 4], [ 6, 7, 5, 8], [10, 11, 9, 12]]) b = a.permute_cols([[0, 2], [0, 1]], direction='backward') assert a.permute([[0, 2], [0, 1]], orientation='cols', direction='backward') == b ==\ Matrix([ [ 3, 1, 2, 4], [ 7, 5, 6, 8], [11, 9, 10, 12]]) assert a.permute([1, 2, 0, 3]) == Matrix([ [5, 6, 7, 8], [9, 10, 11, 12], [1, 2, 3, 4]]) from sympy.combinatorics import Permutation assert a.permute(Permutation([1, 2, 0, 3])) == Matrix([ [5, 6, 7, 8], [9, 10, 11, 12], [1, 2, 3, 4]]) def test_upper_triangular(): A = OperationsOnlyMatrix([ [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1] ]) R = A.upper_triangular(2) assert R == OperationsOnlyMatrix([ [0, 0, 1, 1], [0, 0, 0, 1], [0, 0, 0, 0], [0, 0, 0, 0] ]) R = A.upper_triangular(-2) assert R == OperationsOnlyMatrix([ [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1], [0, 1, 1, 1] ]) R = A.upper_triangular() assert R == OperationsOnlyMatrix([ [1, 1, 1, 1], [0, 1, 1, 1], [0, 0, 1, 1], [0, 0, 0, 1] ]) def test_lower_triangular(): A = OperationsOnlyMatrix([ [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1] ]) L = A.lower_triangular() assert L == ArithmeticOnlyMatrix([ [1, 0, 0, 0], [1, 1, 0, 0], [1, 1, 1, 0], [1, 1, 1, 1]]) L = A.lower_triangular(2) assert L == ArithmeticOnlyMatrix([ [1, 1, 1, 0], [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1] ]) L = A.lower_triangular(-2) assert L == ArithmeticOnlyMatrix([ [0, 0, 0, 0], [0, 0, 0, 0], [1, 0, 0, 0], [1, 1, 0, 0] ]) # ArithmeticOnlyMatrix tests def test_abs(): m = ArithmeticOnlyMatrix([[1, -2], [x, y]]) assert abs(m) == ArithmeticOnlyMatrix([[1, 2], [Abs(x), Abs(y)]]) def test_add(): m = ArithmeticOnlyMatrix([[1, 2, 3], [x, y, x], [2*y, -50, z*x]]) assert m + m == ArithmeticOnlyMatrix([[2, 4, 6], [2*x, 2*y, 2*x], [4*y, -100, 2*z*x]]) n = ArithmeticOnlyMatrix(1, 2, [1, 2]) raises(ShapeError, lambda: m + n) def test_multiplication(): a = ArithmeticOnlyMatrix(( (1, 2), (3, 1), (0, 6), )) b = ArithmeticOnlyMatrix(( (1, 2), (3, 0), )) raises(ShapeError, lambda: b*a) raises(TypeError, lambda: a*{}) c = a*b assert c[0, 0] == 7 assert c[0, 1] == 2 assert c[1, 0] == 6 assert c[1, 1] == 6 assert c[2, 0] == 18 assert c[2, 1] == 0 try: eval('c = a @ b') except SyntaxError: pass else: assert c[0, 0] == 7 assert c[0, 1] == 2 assert c[1, 0] == 6 assert c[1, 1] == 6 assert c[2, 0] == 18 assert c[2, 1] == 0 h = a.multiply_elementwise(c) assert h == matrix_multiply_elementwise(a, c) assert h[0, 0] == 7 assert h[0, 1] == 4 assert h[1, 0] == 18 assert h[1, 1] == 6 assert h[2, 0] == 0 assert h[2, 1] == 0 raises(ShapeError, lambda: a.multiply_elementwise(b)) c = b * Symbol("x") assert isinstance(c, ArithmeticOnlyMatrix) assert c[0, 0] == x assert c[0, 1] == 2*x assert c[1, 0] == 3*x assert c[1, 1] == 0 c2 = x * b assert c == c2 c = 5 * b assert isinstance(c, ArithmeticOnlyMatrix) assert c[0, 0] == 5 assert c[0, 1] == 2*5 assert c[1, 0] == 3*5 assert c[1, 1] == 0 try: eval('c = 5 @ b') except SyntaxError: pass else: assert isinstance(c, ArithmeticOnlyMatrix) assert c[0, 0] == 5 assert c[0, 1] == 2*5 assert c[1, 0] == 3*5 assert c[1, 1] == 0 # https://github.com/sympy/sympy/issues/22353 A = Matrix(ones(3, 1)) _h = -Rational(1, 2) B = Matrix([_h, _h, _h]) assert A.multiply_elementwise(B) == Matrix([ [_h], [_h], [_h]]) def test_matmul(): a = Matrix([[1, 2], [3, 4]]) assert a.__matmul__(2) == NotImplemented assert a.__rmatmul__(2) == NotImplemented #This is done this way because @ is only supported in Python 3.5+ #To check 2@a case try: eval('2 @ a') except SyntaxError: pass except TypeError: #TypeError is raised in case of NotImplemented is returned pass #Check a@2 case try: eval('a @ 2') except SyntaxError: pass except TypeError: #TypeError is raised in case of NotImplemented is returned pass def test_non_matmul(): """ Test that if explicitly specified as non-matrix, mul reverts to scalar multiplication. """ class foo(Expr): is_Matrix=False is_MatrixLike=False shape = (1, 1) A = Matrix([[1, 2], [3, 4]]) b = foo() assert b*A == Matrix([[b, 2*b], [3*b, 4*b]]) assert A*b == Matrix([[b, 2*b], [3*b, 4*b]]) def test_power(): raises(NonSquareMatrixError, lambda: Matrix((1, 2))**2) A = ArithmeticOnlyMatrix([[2, 3], [4, 5]]) assert (A**5)[:] == (6140, 8097, 10796, 14237) A = ArithmeticOnlyMatrix([[2, 1, 3], [4, 2, 4], [6, 12, 1]]) assert (A**3)[:] == (290, 262, 251, 448, 440, 368, 702, 954, 433) assert A**0 == eye(3) assert A**1 == A assert (ArithmeticOnlyMatrix([[2]]) ** 100)[0, 0] == 2**100 assert ArithmeticOnlyMatrix([[1, 2], [3, 4]])**Integer(2) == ArithmeticOnlyMatrix([[7, 10], [15, 22]]) A = Matrix([[1,2],[4,5]]) assert A.pow(20, method='cayley') == A.pow(20, method='multiply') def test_neg(): n = ArithmeticOnlyMatrix(1, 2, [1, 2]) assert -n == ArithmeticOnlyMatrix(1, 2, [-1, -2]) def test_sub(): n = ArithmeticOnlyMatrix(1, 2, [1, 2]) assert n - n == ArithmeticOnlyMatrix(1, 2, [0, 0]) def test_div(): n = ArithmeticOnlyMatrix(1, 2, [1, 2]) assert n/2 == ArithmeticOnlyMatrix(1, 2, [S.Half, S(2)/2]) # SpecialOnlyMatrix tests def test_eye(): assert list(SpecialOnlyMatrix.eye(2, 2)) == [1, 0, 0, 1] assert list(SpecialOnlyMatrix.eye(2)) == [1, 0, 0, 1] assert type(SpecialOnlyMatrix.eye(2)) == SpecialOnlyMatrix assert type(SpecialOnlyMatrix.eye(2, cls=Matrix)) == Matrix def test_ones(): assert list(SpecialOnlyMatrix.ones(2, 2)) == [1, 1, 1, 1] assert list(SpecialOnlyMatrix.ones(2)) == [1, 1, 1, 1] assert SpecialOnlyMatrix.ones(2, 3) == Matrix([[1, 1, 1], [1, 1, 1]]) assert type(SpecialOnlyMatrix.ones(2)) == SpecialOnlyMatrix assert type(SpecialOnlyMatrix.ones(2, cls=Matrix)) == Matrix def test_zeros(): assert list(SpecialOnlyMatrix.zeros(2, 2)) == [0, 0, 0, 0] assert list(SpecialOnlyMatrix.zeros(2)) == [0, 0, 0, 0] assert SpecialOnlyMatrix.zeros(2, 3) == Matrix([[0, 0, 0], [0, 0, 0]]) assert type(SpecialOnlyMatrix.zeros(2)) == SpecialOnlyMatrix assert type(SpecialOnlyMatrix.zeros(2, cls=Matrix)) == Matrix def test_diag_make(): diag = SpecialOnlyMatrix.diag a = Matrix([[1, 2], [2, 3]]) b = Matrix([[3, x], [y, 3]]) c = Matrix([[3, x, 3], [y, 3, z], [x, y, z]]) assert diag(a, b, b) == Matrix([ [1, 2, 0, 0, 0, 0], [2, 3, 0, 0, 0, 0], [0, 0, 3, x, 0, 0], [0, 0, y, 3, 0, 0], [0, 0, 0, 0, 3, x], [0, 0, 0, 0, y, 3], ]) assert diag(a, b, c) == Matrix([ [1, 2, 0, 0, 0, 0, 0], [2, 3, 0, 0, 0, 0, 0], [0, 0, 3, x, 0, 0, 0], [0, 0, y, 3, 0, 0, 0], [0, 0, 0, 0, 3, x, 3], [0, 0, 0, 0, y, 3, z], [0, 0, 0, 0, x, y, z], ]) assert diag(a, c, b) == Matrix([ [1, 2, 0, 0, 0, 0, 0], [2, 3, 0, 0, 0, 0, 0], [0, 0, 3, x, 3, 0, 0], [0, 0, y, 3, z, 0, 0], [0, 0, x, y, z, 0, 0], [0, 0, 0, 0, 0, 3, x], [0, 0, 0, 0, 0, y, 3], ]) a = Matrix([x, y, z]) b = Matrix([[1, 2], [3, 4]]) c = Matrix([[5, 6]]) # this "wandering diagonal" is what makes this # a block diagonal where each block is independent # of the others assert diag(a, 7, b, c) == Matrix([ [x, 0, 0, 0, 0, 0], [y, 0, 0, 0, 0, 0], [z, 0, 0, 0, 0, 0], [0, 7, 0, 0, 0, 0], [0, 0, 1, 2, 0, 0], [0, 0, 3, 4, 0, 0], [0, 0, 0, 0, 5, 6]]) raises(ValueError, lambda: diag(a, 7, b, c, rows=5)) assert diag(1) == Matrix([[1]]) assert diag(1, rows=2) == Matrix([[1, 0], [0, 0]]) assert diag(1, cols=2) == Matrix([[1, 0], [0, 0]]) assert diag(1, rows=3, cols=2) == Matrix([[1, 0], [0, 0], [0, 0]]) assert diag(*[2, 3]) == Matrix([ [2, 0], [0, 3]]) assert diag(Matrix([2, 3])) == Matrix([ [2], [3]]) assert diag([1, [2, 3], 4], unpack=False) == \ diag([[1], [2, 3], [4]], unpack=False) == Matrix([ [1, 0], [2, 3], [4, 0]]) assert type(diag(1)) == SpecialOnlyMatrix assert type(diag(1, cls=Matrix)) == Matrix assert Matrix.diag([1, 2, 3]) == Matrix.diag(1, 2, 3) assert Matrix.diag([1, 2, 3], unpack=False).shape == (3, 1) assert Matrix.diag([[1, 2, 3]]).shape == (3, 1) assert Matrix.diag([[1, 2, 3]], unpack=False).shape == (1, 3) assert Matrix.diag([[[1, 2, 3]]]).shape == (1, 3) # kerning can be used to move the starting point assert Matrix.diag(ones(0, 2), 1, 2) == Matrix([ [0, 0, 1, 0], [0, 0, 0, 2]]) assert Matrix.diag(ones(2, 0), 1, 2) == Matrix([ [0, 0], [0, 0], [1, 0], [0, 2]]) def test_diagonal(): m = Matrix(3, 3, range(9)) d = m.diagonal() assert d == m.diagonal(0) assert tuple(d) == (0, 4, 8) assert tuple(m.diagonal(1)) == (1, 5) assert tuple(m.diagonal(-1)) == (3, 7) assert tuple(m.diagonal(2)) == (2,) assert type(m.diagonal()) == type(m) s = SparseMatrix(3, 3, {(1, 1): 1}) assert type(s.diagonal()) == type(s) assert type(m) != type(s) raises(ValueError, lambda: m.diagonal(3)) raises(ValueError, lambda: m.diagonal(-3)) raises(ValueError, lambda: m.diagonal(pi)) M = ones(2, 3) assert banded({i: list(M.diagonal(i)) for i in range(1-M.rows, M.cols)}) == M def test_jordan_block(): assert SpecialOnlyMatrix.jordan_block(3, 2) == SpecialOnlyMatrix.jordan_block(3, eigenvalue=2) \ == SpecialOnlyMatrix.jordan_block(size=3, eigenvalue=2) \ == SpecialOnlyMatrix.jordan_block(3, 2, band='upper') \ == SpecialOnlyMatrix.jordan_block( size=3, eigenval=2, eigenvalue=2) \ == Matrix([ [2, 1, 0], [0, 2, 1], [0, 0, 2]]) assert SpecialOnlyMatrix.jordan_block(3, 2, band='lower') == Matrix([ [2, 0, 0], [1, 2, 0], [0, 1, 2]]) # missing eigenvalue raises(ValueError, lambda: SpecialOnlyMatrix.jordan_block(2)) # non-integral size raises(ValueError, lambda: SpecialOnlyMatrix.jordan_block(3.5, 2)) # size not specified raises(ValueError, lambda: SpecialOnlyMatrix.jordan_block(eigenvalue=2)) # inconsistent eigenvalue raises(ValueError, lambda: SpecialOnlyMatrix.jordan_block( eigenvalue=2, eigenval=4)) # Using alias keyword assert SpecialOnlyMatrix.jordan_block(size=3, eigenvalue=2) == \ SpecialOnlyMatrix.jordan_block(size=3, eigenval=2) def test_orthogonalize(): m = Matrix([[1, 2], [3, 4]]) assert m.orthogonalize(Matrix([[2], [1]])) == [Matrix([[2], [1]])] assert m.orthogonalize(Matrix([[2], [1]]), normalize=True) == \ [Matrix([[2*sqrt(5)/5], [sqrt(5)/5]])] assert m.orthogonalize(Matrix([[1], [2]]), Matrix([[-1], [4]])) == \ [Matrix([[1], [2]]), Matrix([[Rational(-12, 5)], [Rational(6, 5)]])] assert m.orthogonalize(Matrix([[0], [0]]), Matrix([[-1], [4]])) == \ [Matrix([[-1], [4]])] assert m.orthogonalize(Matrix([[0], [0]])) == [] n = Matrix([[9, 1, 9], [3, 6, 10], [8, 5, 2]]) vecs = [Matrix([[-5], [1]]), Matrix([[-5], [2]]), Matrix([[-5], [-2]])] assert n.orthogonalize(*vecs) == \ [Matrix([[-5], [1]]), Matrix([[Rational(5, 26)], [Rational(25, 26)]])] vecs = [Matrix([0, 0, 0]), Matrix([1, 2, 3]), Matrix([1, 4, 5])] raises(ValueError, lambda: Matrix.orthogonalize(*vecs, rankcheck=True)) vecs = [Matrix([1, 2, 3]), Matrix([4, 5, 6]), Matrix([7, 8, 9])] raises(ValueError, lambda: Matrix.orthogonalize(*vecs, rankcheck=True)) def test_wilkinson(): wminus, wplus = Matrix.wilkinson(1) assert wminus == Matrix([ [-1, 1, 0], [1, 0, 1], [0, 1, 1]]) assert wplus == Matrix([ [1, 1, 0], [1, 0, 1], [0, 1, 1]]) wminus, wplus = Matrix.wilkinson(3) assert wminus == Matrix([ [-3, 1, 0, 0, 0, 0, 0], [1, -2, 1, 0, 0, 0, 0], [0, 1, -1, 1, 0, 0, 0], [0, 0, 1, 0, 1, 0, 0], [0, 0, 0, 1, 1, 1, 0], [0, 0, 0, 0, 1, 2, 1], [0, 0, 0, 0, 0, 1, 3]]) assert wplus == Matrix([ [3, 1, 0, 0, 0, 0, 0], [1, 2, 1, 0, 0, 0, 0], [0, 1, 1, 1, 0, 0, 0], [0, 0, 1, 0, 1, 0, 0], [0, 0, 0, 1, 1, 1, 0], [0, 0, 0, 0, 1, 2, 1], [0, 0, 0, 0, 0, 1, 3]]) # CalculusOnlyMatrix tests @XFAIL def test_diff(): x, y = symbols('x y') m = CalculusOnlyMatrix(2, 1, [x, y]) # TODO: currently not working as ``_MinimalMatrix`` cannot be sympified: assert m.diff(x) == Matrix(2, 1, [1, 0]) def test_integrate(): x, y = symbols('x y') m = CalculusOnlyMatrix(2, 1, [x, y]) assert m.integrate(x) == Matrix(2, 1, [x**2/2, y*x]) def test_jacobian2(): rho, phi = symbols("rho,phi") X = CalculusOnlyMatrix(3, 1, [rho*cos(phi), rho*sin(phi), rho**2]) Y = CalculusOnlyMatrix(2, 1, [rho, phi]) J = Matrix([ [cos(phi), -rho*sin(phi)], [sin(phi), rho*cos(phi)], [ 2*rho, 0], ]) assert X.jacobian(Y) == J m = CalculusOnlyMatrix(2, 2, [1, 2, 3, 4]) m2 = CalculusOnlyMatrix(4, 1, [1, 2, 3, 4]) raises(TypeError, lambda: m.jacobian(Matrix([1, 2]))) raises(TypeError, lambda: m2.jacobian(m)) def test_limit(): x, y = symbols('x y') m = CalculusOnlyMatrix(2, 1, [1/x, y]) assert m.limit(x, 5) == Matrix(2, 1, [Rational(1, 5), y]) def test_issue_13774(): M = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) v = [1, 1, 1] raises(TypeError, lambda: M*v) raises(TypeError, lambda: v*M) def test_companion(): x = Symbol('x') y = Symbol('y') raises(ValueError, lambda: Matrix.companion(1)) raises(ValueError, lambda: Matrix.companion(Poly([1], x))) raises(ValueError, lambda: Matrix.companion(Poly([2, 1], x))) raises(ValueError, lambda: Matrix.companion(Poly(x*y, [x, y]))) c0, c1, c2 = symbols('c0:3') assert Matrix.companion(Poly([1, c0], x)) == Matrix([-c0]) assert Matrix.companion(Poly([1, c1, c0], x)) == \ Matrix([[0, -c0], [1, -c1]]) assert Matrix.companion(Poly([1, c2, c1, c0], x)) == \ Matrix([[0, 0, -c0], [1, 0, -c1], [0, 1, -c2]]) def test_issue_10589(): x, y, z = symbols("x, y z") M1 = Matrix([x, y, z]) M1 = M1.subs(zip([x, y, z], [1, 2, 3])) assert M1 == Matrix([[1], [2], [3]]) M2 = Matrix([[x, x, x, x, x], [x, x, x, x, x], [x, x, x, x, x]]) M2 = M2.subs(zip([x], [1])) assert M2 == Matrix([[1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1]]) def test_rmul_pr19860(): class Foo(ImmutableDenseMatrix): _op_priority = MutableDenseMatrix._op_priority + 0.01 a = Matrix(2, 2, [1, 2, 3, 4]) b = Foo(2, 2, [1, 2, 3, 4]) # This would throw a RecursionError: maximum recursion depth # since b always has higher priority even after a.as_mutable() c = a*b assert isinstance(c, Foo) assert c == Matrix([[7, 10], [15, 22]]) def test_issue_18956(): A = Array([[1, 2], [3, 4]]) B = Matrix([[1,2],[3,4]]) raises(TypeError, lambda: B + A) raises(TypeError, lambda: A + B) def test__eq__(): class My(object): def __iter__(self): yield 1 yield 2 return def __getitem__(self, i): return list(self)[i] a = Matrix(2, 1, [1, 2]) assert a != My() class My_sympy(My): def _sympy_(self): return Matrix(self) assert a == My_sympy()