2

I have two small but very complicated matrices that I want to multiply. I've done this using sympy:

C=sympy.MatMul(A,B,hold=True)

This gives me a MatMul object which saves a huge amount of time, and I'm not interested in a symbolic expression anyway, rather I want to evaluate at specific points later on.

If this was the end of my calculation it would be fine, but I then need to use elements of C in order to define a new equation, however, I cannot index it. I get the following,

In [286]: C[0]
Traceback (most recent call last):

  File "<ipython-input-286-829e2440bf19>", line 1, in <module>
    C[0]

  File "C:\Anaconda3\lib\site-packages\sympy\matrices\expressions\matexpr.py", line 242, in __getitem__
    raise IndexError("Single index only supported for "

IndexError: Single index only supported for non-symbolic matrix shapes.

Is it possible to somehow index such an object? For example, in maple I can use a semi-colon which suppresses the output, while retaining information about the structure of the resulting object so I can index it.

ben_afobe
  • 95
  • 4

2 Answers2

3

You can index elements of C, e.g. C[0,0]. So this will give you the first row as a list:

row0 = [C[0, k] for k in range(C.shape[1])]

Here's an example. x and y are sympy symbols.

In [40]: A
Out[40]: 
Matrix([
[2*x + 1, x + 3],
[     -2,     3]])

In [41]: B
Out[41]: 
Matrix([
[-3,   3],
[ y, 2*y]])

In [42]: C = sympy.MatMul(A, B, hold=True)

In [43]: C[0,0]
Out[43]: -6*x + y*(x + 3) - 3

In [44]: [C[0,k] for k in range(C.shape[1])]
Out[44]: [-6*x + y*(x + 3) - 3, 6*x + 2*y*(x + 3) + 3]
Warren Weckesser
  • 110,654
  • 19
  • 194
  • 214
1

To explain the error, normally, a single index indexes a matrix row-by-row:

In [8]: M = Matrix([[1, 2], [3, 4]])

In [9]: M
Out[9]:
⎡1  2⎤
⎢    ⎥
⎣3  4⎦

In [10]: M[0]
Out[10]: 1

In [11]: M[1]
Out[11]: 2

In [12]: M[2]
Out[12]: 3

In [14]: M[3]
Out[14]: 4

For a symbolic matrix symbol, this is computed as the row,column index. For instance,

In [16]: MatrixSymbol('A', 3, 4)[0]
Out[16]: A₀₀

In [17]: MatrixSymbol('A', 3, 4)[10]
Out[17]: A₂₂

The element A[10] is automatically converted to A[2, 2], because A has 4 columns, so 10 is the third column of the third row (remember that everything is 0-indexed).

However, if your shape is symbolic, particularly the number of columns, say A is m x n, there is no way to know which row,column A[i] refers to (n % i is symbolic). Probably, SymPy could be changed to make A[i] return A[i//n,i%n] symbolically, but you generally want to explicitly reference matrix elements by row,column anyway, so if you really want that, you could just do it manually. Also, this formula has no bounds checking (if i >= n*m the element is out of bounds).

Strictly speaking, A[0] could probably work, since that will always be A[0, 0] regardless of the shape of A. However, this would be a single special-case, and SymPy has chosen to disallow it, since it's possible to just write the explicit A[0, 0] anyway.

asmeurer
  • 86,894
  • 26
  • 169
  • 240