__init__.py 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. r"""
  2. Array expressions are expressions representing N-dimensional arrays, without
  3. evaluating them. These expressions represent in a certain way abstract syntax
  4. trees of operations on N-dimensional arrays.
  5. Every N-dimensional array operator has a corresponding array expression object.
  6. Table of correspondences:
  7. =============================== =============================
  8. Array operator Array expression operator
  9. =============================== =============================
  10. tensorproduct ArrayTensorProduct
  11. tensorcontraction ArrayContraction
  12. tensordiagonal ArrayDiagonal
  13. permutedims PermuteDims
  14. =============================== =============================
  15. Examples
  16. ========
  17. ``ArraySymbol`` objects are the N-dimensional equivalent of ``MatrixSymbol``
  18. objects in the matrix module:
  19. >>> from sympy.tensor.array.expressions import ArraySymbol
  20. >>> from sympy.abc import i, j, k
  21. >>> A = ArraySymbol("A", (3, 2, 4))
  22. >>> A.shape
  23. (3, 2, 4)
  24. >>> A[i, j, k]
  25. A[i, j, k]
  26. >>> A.as_explicit()
  27. [[[A[0, 0, 0], A[0, 0, 1], A[0, 0, 2], A[0, 0, 3]],
  28. [A[0, 1, 0], A[0, 1, 1], A[0, 1, 2], A[0, 1, 3]]],
  29. [[A[1, 0, 0], A[1, 0, 1], A[1, 0, 2], A[1, 0, 3]],
  30. [A[1, 1, 0], A[1, 1, 1], A[1, 1, 2], A[1, 1, 3]]],
  31. [[A[2, 0, 0], A[2, 0, 1], A[2, 0, 2], A[2, 0, 3]],
  32. [A[2, 1, 0], A[2, 1, 1], A[2, 1, 2], A[2, 1, 3]]]]
  33. Component-explicit arrays can be added inside array expressions:
  34. >>> from sympy import Array
  35. >>> from sympy import tensorproduct
  36. >>> from sympy.tensor.array.expressions import ArrayTensorProduct
  37. >>> a = Array([1, 2, 3])
  38. >>> b = Array([i, j, k])
  39. >>> expr = ArrayTensorProduct(a, b, b)
  40. >>> expr
  41. ArrayTensorProduct([1, 2, 3], [i, j, k], [i, j, k])
  42. >>> expr.as_explicit() == tensorproduct(a, b, b)
  43. True
  44. Constructing array expressions from index-explicit forms
  45. --------------------------------------------------------
  46. Array expressions are index-implicit. This means they do not use any indices to
  47. represent array operations. The function ``convert_indexed_to_array( ... )``
  48. may be used to convert index-explicit expressions to array expressions.
  49. It takes as input two parameters: the index-explicit expression and the order
  50. of the indices:
  51. >>> from sympy.tensor.array.expressions import convert_indexed_to_array
  52. >>> from sympy import Sum
  53. >>> A = ArraySymbol("A", (3, 3))
  54. >>> B = ArraySymbol("B", (3, 3))
  55. >>> convert_indexed_to_array(A[i, j], [i, j])
  56. A
  57. >>> convert_indexed_to_array(A[i, j], [j, i])
  58. PermuteDims(A, (0 1))
  59. >>> convert_indexed_to_array(A[i, j] + B[j, i], [i, j])
  60. ArrayAdd(A, PermuteDims(B, (0 1)))
  61. >>> convert_indexed_to_array(Sum(A[i, j]*B[j, k], (j, 0, 2)), [i, k])
  62. ArrayContraction(ArrayTensorProduct(A, B), (1, 2))
  63. The diagonal of a matrix in the array expression form:
  64. >>> convert_indexed_to_array(A[i, i], [i])
  65. ArrayDiagonal(A, (0, 1))
  66. The trace of a matrix in the array expression form:
  67. >>> convert_indexed_to_array(Sum(A[i, i], (i, 0, 2)), [i])
  68. ArrayContraction(A, (0, 1))
  69. Compatibility with matrices
  70. ---------------------------
  71. Array expressions can be mixed with objects from the matrix module:
  72. >>> from sympy import MatrixSymbol
  73. >>> from sympy.tensor.array.expressions import ArrayContraction
  74. >>> M = MatrixSymbol("M", 3, 3)
  75. >>> N = MatrixSymbol("N", 3, 3)
  76. Express the matrix product in the array expression form:
  77. >>> from sympy.tensor.array.expressions import convert_matrix_to_array
  78. >>> expr = convert_matrix_to_array(M*N)
  79. >>> expr
  80. ArrayContraction(ArrayTensorProduct(M, N), (1, 2))
  81. The expression can be converted back to matrix form:
  82. >>> from sympy.tensor.array.expressions import convert_array_to_matrix
  83. >>> convert_array_to_matrix(expr)
  84. M*N
  85. Add a second contraction on the remaining axes in order to get the trace of `M \cdot N`:
  86. >>> expr_tr = ArrayContraction(expr, (0, 1))
  87. >>> expr_tr
  88. ArrayContraction(ArrayContraction(ArrayTensorProduct(M, N), (1, 2)), (0, 1))
  89. Flatten the expression by calling ``.doit()`` and remove the nested array contraction operations:
  90. >>> expr_tr.doit()
  91. ArrayContraction(ArrayTensorProduct(M, N), (0, 3), (1, 2))
  92. Get the explicit form of the array expression:
  93. >>> expr.as_explicit()
  94. [[M[0, 0]*N[0, 0] + M[0, 1]*N[1, 0] + M[0, 2]*N[2, 0], M[0, 0]*N[0, 1] + M[0, 1]*N[1, 1] + M[0, 2]*N[2, 1], M[0, 0]*N[0, 2] + M[0, 1]*N[1, 2] + M[0, 2]*N[2, 2]],
  95. [M[1, 0]*N[0, 0] + M[1, 1]*N[1, 0] + M[1, 2]*N[2, 0], M[1, 0]*N[0, 1] + M[1, 1]*N[1, 1] + M[1, 2]*N[2, 1], M[1, 0]*N[0, 2] + M[1, 1]*N[1, 2] + M[1, 2]*N[2, 2]],
  96. [M[2, 0]*N[0, 0] + M[2, 1]*N[1, 0] + M[2, 2]*N[2, 0], M[2, 0]*N[0, 1] + M[2, 1]*N[1, 1] + M[2, 2]*N[2, 1], M[2, 0]*N[0, 2] + M[2, 1]*N[1, 2] + M[2, 2]*N[2, 2]]]
  97. Express the trace of a matrix:
  98. >>> from sympy import Trace
  99. >>> convert_matrix_to_array(Trace(M))
  100. ArrayContraction(M, (0, 1))
  101. >>> convert_matrix_to_array(Trace(M*N))
  102. ArrayContraction(ArrayTensorProduct(M, N), (0, 3), (1, 2))
  103. Express the transposition of a matrix (will be expressed as a permutation of the axes:
  104. >>> convert_matrix_to_array(M.T)
  105. PermuteDims(M, (0 1))
  106. Compute the derivative array expressions:
  107. >>> from sympy.tensor.array.expressions import array_derive
  108. >>> d = array_derive(M, M)
  109. >>> d
  110. PermuteDims(ArrayTensorProduct(I, I), (3)(1 2))
  111. Verify that the derivative corresponds to the form computed with explicit matrices:
  112. >>> d.as_explicit()
  113. [[[[1, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 1, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 1], [0, 0, 0], [0, 0, 0]]], [[[0, 0, 0], [1, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 1, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 1], [0, 0, 0]]], [[[0, 0, 0], [0, 0, 0], [1, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 1, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 1]]]]
  114. >>> Me = M.as_explicit()
  115. >>> Me.diff(Me)
  116. [[[[1, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 1, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 1], [0, 0, 0], [0, 0, 0]]], [[[0, 0, 0], [1, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 1, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 1], [0, 0, 0]]], [[[0, 0, 0], [0, 0, 0], [1, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 1, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 1]]]]
  117. """
  118. __all__ = [
  119. "ArraySymbol", "ArrayElement", "ZeroArray", "OneArray",
  120. "ArrayTensorProduct",
  121. "ArrayContraction",
  122. "ArrayDiagonal",
  123. "PermuteDims",
  124. "ArrayAdd",
  125. "ArrayElementwiseApplyFunc",
  126. "Reshape",
  127. "convert_array_to_matrix",
  128. "convert_matrix_to_array",
  129. "convert_array_to_indexed",
  130. "convert_indexed_to_array",
  131. "array_derive",
  132. ]
  133. from sympy.tensor.array.expressions.array_expressions import ArrayTensorProduct, ArrayAdd, PermuteDims, ArrayDiagonal, \
  134. ArrayContraction, Reshape, ArraySymbol, ArrayElement, ZeroArray, OneArray, ArrayElementwiseApplyFunc
  135. from sympy.tensor.array.expressions.arrayexpr_derivatives import array_derive
  136. from sympy.tensor.array.expressions.from_array_to_indexed import convert_array_to_indexed
  137. from sympy.tensor.array.expressions.from_array_to_matrix import convert_array_to_matrix
  138. from sympy.tensor.array.expressions.from_indexed_to_array import convert_indexed_to_array
  139. from sympy.tensor.array.expressions.from_matrix_to_array import convert_matrix_to_array