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

1from mpmath.matrices.matrices import _matrix 

2 

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 

13 

14 

15def sympify_matrix(arg): 

16 return arg.as_immutable() 

17 

18 

19sympify_converter[MatrixBase] = sympify_matrix 

20 

21 

22def sympify_mpmath_matrix(arg): 

23 mat = [_sympify(x) for x in arg] 

24 return ImmutableDenseMatrix(arg.rows, arg.cols, mat) 

25 

26 

27sympify_converter[_matrix] = sympify_mpmath_matrix 

28 

29 

30class ImmutableRepMatrix(RepMatrix, MatrixExpr): # type: ignore 

31 """Immutable matrix based on RepMatrix 

32 

33 Uses DomainMAtrix as the internal representation. 

34 """ 

35 

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 # 

41 

42 def __new__(cls, *args, **kwargs): 

43 return cls._new(*args, **kwargs) 

44 

45 __hash__ = MatrixExpr.__hash__ 

46 

47 def copy(self): 

48 return self 

49 

50 @property 

51 def cols(self): 

52 return self._cols 

53 

54 @property 

55 def rows(self): 

56 return self._rows 

57 

58 @property 

59 def shape(self): 

60 return self._rows, self._cols 

61 

62 def as_immutable(self): 

63 return self 

64 

65 def _entry(self, i, j, **kwargs): 

66 return self[i, j] 

67 

68 def __setitem__(self, *args): 

69 raise TypeError("Cannot set values of {}".format(self.__class__)) 

70 

71 def is_diagonalizable(self, reals_only=False, **kwargs): 

72 return super().is_diagonalizable( 

73 reals_only=reals_only, **kwargs) 

74 

75 is_diagonalizable.__doc__ = SparseRepMatrix.is_diagonalizable.__doc__ 

76 is_diagonalizable = cacheit(is_diagonalizable) 

77 

78 

79 

80class ImmutableDenseMatrix(DenseMatrix, ImmutableRepMatrix): # type: ignore 

81 """Create an immutable version of a matrix. 

82 

83 Examples 

84 ======== 

85 

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 """ 

97 

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 

103 

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 

115 

116 rep = cls._flat_list_to_DomainMatrix(rows, cols, flat_list) 

117 

118 return cls._fromrep(rep) 

119 

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 

132 

133 

134# make sure ImmutableDenseMatrix is aliased as ImmutableMatrix 

135ImmutableMatrix = ImmutableDenseMatrix 

136 

137 

138class ImmutableSparseMatrix(SparseRepMatrix, ImmutableRepMatrix): # type:ignore 

139 """Create an immutable version of a sparse matrix. 

140 

141 Examples 

142 ======== 

143 

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 

161 

162 @classmethod 

163 def _new(cls, *args, **kwargs): 

164 rows, cols, smat = cls._handle_creation_inputs(*args, **kwargs) 

165 

166 rep = cls._smat_to_DomainMatrix(rows, cols, smat) 

167 

168 return cls._fromrep(rep) 

169 

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 

179 

180 

181@dispatch(ImmutableDenseMatrix, ImmutableDenseMatrix) 

182def _eval_is_eq(lhs, rhs): # noqa:F811 

183 """Helper method for Equality with matrices.sympy. 

184 

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. 

190 

191 """ 

192 if lhs.shape != rhs.shape: 

193 return False 

194 return (lhs - rhs).is_zero_matrix