Coverage for /usr/lib/python3/dist-packages/sympy/matrices/expressions/funcmatrix.py: 44%

34 statements  

« prev     ^ index     » next       coverage.py v7.9.1, created at 2025-06-14 15:55 +0200

1from .matexpr import MatrixExpr 

2from sympy.core.function import FunctionClass, Lambda 

3from sympy.core.symbol import Dummy 

4from sympy.core.sympify import _sympify, sympify 

5from sympy.matrices import Matrix 

6from sympy.functions.elementary.complexes import re, im 

7 

8 

9class FunctionMatrix(MatrixExpr): 

10 """Represents a matrix using a function (``Lambda``) which gives 

11 outputs according to the coordinates of each matrix entries. 

12 

13 Parameters 

14 ========== 

15 

16 rows : nonnegative integer. Can be symbolic. 

17 

18 cols : nonnegative integer. Can be symbolic. 

19 

20 lamda : Function, Lambda or str 

21 If it is a SymPy ``Function`` or ``Lambda`` instance, 

22 it should be able to accept two arguments which represents the 

23 matrix coordinates. 

24 

25 If it is a pure string containing Python ``lambda`` semantics, 

26 it is interpreted by the SymPy parser and casted into a SymPy 

27 ``Lambda`` instance. 

28 

29 Examples 

30 ======== 

31 

32 Creating a ``FunctionMatrix`` from ``Lambda``: 

33 

34 >>> from sympy import FunctionMatrix, symbols, Lambda, MatPow 

35 >>> i, j, n, m = symbols('i,j,n,m') 

36 >>> FunctionMatrix(n, m, Lambda((i, j), i + j)) 

37 FunctionMatrix(n, m, Lambda((i, j), i + j)) 

38 

39 Creating a ``FunctionMatrix`` from a SymPy function: 

40 

41 >>> from sympy import KroneckerDelta 

42 >>> X = FunctionMatrix(3, 3, KroneckerDelta) 

43 >>> X.as_explicit() 

44 Matrix([ 

45 [1, 0, 0], 

46 [0, 1, 0], 

47 [0, 0, 1]]) 

48 

49 Creating a ``FunctionMatrix`` from a SymPy undefined function: 

50 

51 >>> from sympy import Function 

52 >>> f = Function('f') 

53 >>> X = FunctionMatrix(3, 3, f) 

54 >>> X.as_explicit() 

55 Matrix([ 

56 [f(0, 0), f(0, 1), f(0, 2)], 

57 [f(1, 0), f(1, 1), f(1, 2)], 

58 [f(2, 0), f(2, 1), f(2, 2)]]) 

59 

60 Creating a ``FunctionMatrix`` from Python ``lambda``: 

61 

62 >>> FunctionMatrix(n, m, 'lambda i, j: i + j') 

63 FunctionMatrix(n, m, Lambda((i, j), i + j)) 

64 

65 Example of lazy evaluation of matrix product: 

66 

67 >>> Y = FunctionMatrix(1000, 1000, Lambda((i, j), i + j)) 

68 >>> isinstance(Y*Y, MatPow) # this is an expression object 

69 True 

70 >>> (Y**2)[10,10] # So this is evaluated lazily 

71 342923500 

72 

73 Notes 

74 ===== 

75 

76 This class provides an alternative way to represent an extremely 

77 dense matrix with entries in some form of a sequence, in a most 

78 sparse way. 

79 """ 

80 def __new__(cls, rows, cols, lamda): 

81 rows, cols = _sympify(rows), _sympify(cols) 

82 cls._check_dim(rows) 

83 cls._check_dim(cols) 

84 

85 lamda = sympify(lamda) 

86 if not isinstance(lamda, (FunctionClass, Lambda)): 

87 raise ValueError( 

88 "{} should be compatible with SymPy function classes." 

89 .format(lamda)) 

90 

91 if 2 not in lamda.nargs: 

92 raise ValueError( 

93 '{} should be able to accept 2 arguments.'.format(lamda)) 

94 

95 if not isinstance(lamda, Lambda): 

96 i, j = Dummy('i'), Dummy('j') 

97 lamda = Lambda((i, j), lamda(i, j)) 

98 

99 return super().__new__(cls, rows, cols, lamda) 

100 

101 @property 

102 def shape(self): 

103 return self.args[0:2] 

104 

105 @property 

106 def lamda(self): 

107 return self.args[2] 

108 

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

110 return self.lamda(i, j) 

111 

112 def _eval_trace(self): 

113 from sympy.matrices.expressions.trace import Trace 

114 from sympy.concrete.summations import Sum 

115 return Trace(self).rewrite(Sum).doit() 

116 

117 def _eval_as_real_imag(self): 

118 return (re(Matrix(self)), im(Matrix(self)))