Coverage for /usr/lib/python3/dist-packages/sympy/matrices/immutable.py: 54%
91 statements
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-14 15:55 +0200
« prev ^ index » next coverage.py v7.9.1, created at 2025-06-14 15:55 +0200
1from mpmath.matrices.matrices import _matrix
3from sympy.core import Basic, Dict, Tuple
4from sympy.core.numbers import Integer
5from sympy.core.cache import cacheit
6from sympy.core.sympify import _sympy_converter as sympify_converter, _sympify
7from sympy.matrices.dense import DenseMatrix
8from sympy.matrices.expressions import MatrixExpr
9from sympy.matrices.matrices import MatrixBase
10from sympy.matrices.repmatrix import RepMatrix
11from sympy.matrices.sparse import SparseRepMatrix
12from sympy.multipledispatch import dispatch
15def sympify_matrix(arg):
16 return arg.as_immutable()
19sympify_converter[MatrixBase] = sympify_matrix
22def sympify_mpmath_matrix(arg):
23 mat = [_sympify(x) for x in arg]
24 return ImmutableDenseMatrix(arg.rows, arg.cols, mat)
27sympify_converter[_matrix] = sympify_mpmath_matrix
30class ImmutableRepMatrix(RepMatrix, MatrixExpr): # type: ignore
31 """Immutable matrix based on RepMatrix
33 Uses DomainMAtrix as the internal representation.
34 """
36 #
37 # This is a subclass of RepMatrix that adds/overrides some methods to make
38 # the instances Basic and immutable. ImmutableRepMatrix is a superclass for
39 # both ImmutableDenseMatrix and ImmutableSparseMatrix.
40 #
42 def __new__(cls, *args, **kwargs):
43 return cls._new(*args, **kwargs)
45 __hash__ = MatrixExpr.__hash__
47 def copy(self):
48 return self
50 @property
51 def cols(self):
52 return self._cols
54 @property
55 def rows(self):
56 return self._rows
58 @property
59 def shape(self):
60 return self._rows, self._cols
62 def as_immutable(self):
63 return self
65 def _entry(self, i, j, **kwargs):
66 return self[i, j]
68 def __setitem__(self, *args):
69 raise TypeError("Cannot set values of {}".format(self.__class__))
71 def is_diagonalizable(self, reals_only=False, **kwargs):
72 return super().is_diagonalizable(
73 reals_only=reals_only, **kwargs)
75 is_diagonalizable.__doc__ = SparseRepMatrix.is_diagonalizable.__doc__
76 is_diagonalizable = cacheit(is_diagonalizable)
80class ImmutableDenseMatrix(DenseMatrix, ImmutableRepMatrix): # type: ignore
81 """Create an immutable version of a matrix.
83 Examples
84 ========
86 >>> from sympy import eye, ImmutableMatrix
87 >>> ImmutableMatrix(eye(3))
88 Matrix([
89 [1, 0, 0],
90 [0, 1, 0],
91 [0, 0, 1]])
92 >>> _[0, 0] = 42
93 Traceback (most recent call last):
94 ...
95 TypeError: Cannot set values of ImmutableDenseMatrix
96 """
98 # MatrixExpr is set as NotIterable, but we want explicit matrices to be
99 # iterable
100 _iterable = True
101 _class_priority = 8
102 _op_priority = 10.001
104 @classmethod
105 def _new(cls, *args, **kwargs):
106 if len(args) == 1 and isinstance(args[0], ImmutableDenseMatrix):
107 return args[0]
108 if kwargs.get('copy', True) is False:
109 if len(args) != 3:
110 raise TypeError("'copy=False' requires a matrix be initialized as rows,cols,[list]")
111 rows, cols, flat_list = args
112 else:
113 rows, cols, flat_list = cls._handle_creation_inputs(*args, **kwargs)
114 flat_list = list(flat_list) # create a shallow copy
116 rep = cls._flat_list_to_DomainMatrix(rows, cols, flat_list)
118 return cls._fromrep(rep)
120 @classmethod
121 def _fromrep(cls, rep):
122 rows, cols = rep.shape
123 flat_list = rep.to_sympy().to_list_flat()
124 obj = Basic.__new__(cls,
125 Integer(rows),
126 Integer(cols),
127 Tuple(*flat_list, sympify=False))
128 obj._rows = rows
129 obj._cols = cols
130 obj._rep = rep
131 return obj
134# make sure ImmutableDenseMatrix is aliased as ImmutableMatrix
135ImmutableMatrix = ImmutableDenseMatrix
138class ImmutableSparseMatrix(SparseRepMatrix, ImmutableRepMatrix): # type:ignore
139 """Create an immutable version of a sparse matrix.
141 Examples
142 ========
144 >>> from sympy import eye, ImmutableSparseMatrix
145 >>> ImmutableSparseMatrix(1, 1, {})
146 Matrix([[0]])
147 >>> ImmutableSparseMatrix(eye(3))
148 Matrix([
149 [1, 0, 0],
150 [0, 1, 0],
151 [0, 0, 1]])
152 >>> _[0, 0] = 42
153 Traceback (most recent call last):
154 ...
155 TypeError: Cannot set values of ImmutableSparseMatrix
156 >>> _.shape
157 (3, 3)
158 """
159 is_Matrix = True
160 _class_priority = 9
162 @classmethod
163 def _new(cls, *args, **kwargs):
164 rows, cols, smat = cls._handle_creation_inputs(*args, **kwargs)
166 rep = cls._smat_to_DomainMatrix(rows, cols, smat)
168 return cls._fromrep(rep)
170 @classmethod
171 def _fromrep(cls, rep):
172 rows, cols = rep.shape
173 smat = rep.to_sympy().to_dok()
174 obj = Basic.__new__(cls, Integer(rows), Integer(cols), Dict(smat))
175 obj._rows = rows
176 obj._cols = cols
177 obj._rep = rep
178 return obj
181@dispatch(ImmutableDenseMatrix, ImmutableDenseMatrix)
182def _eval_is_eq(lhs, rhs): # noqa:F811
183 """Helper method for Equality with matrices.sympy.
185 Relational automatically converts matrices to ImmutableDenseMatrix
186 instances, so this method only applies here. Returns True if the
187 matrices are definitively the same, False if they are definitively
188 different, and None if undetermined (e.g. if they contain Symbols).
189 Returning None triggers default handling of Equalities.
191 """
192 if lhs.shape != rhs.shape:
193 return False
194 return (lhs - rhs).is_zero_matrix