Siv Scripts

Solving Problems Using Code

Fri 05 January 2018

@ Python's Matrix Multiplication Operator

Posted by Aly Sivji in Quick Hits   

2017 will forever be etched in our memories as the year Python overtook R to become the leading language for Data Science. There are many factors that play into this: Python's simple syntax, the fantastic PyData ecosystem, and of course buy-in from Python's BDFL.

PEP 465 introduced the @ infix operator that is designated to be used for matrix multiplication. The acceptance and implementation of this proposal in Python 3.5 was a signal to the scientific community that Python is taking its role as a numerical computation language very seriously.

I was a Computational Mathematics major in college so matrices are very near and dear to my heart. Shoutout to Professor Jeff Orchard for having us implement matrix algorithms in C++. His Numerical Linear Algebra course was the best class I've ever taken.

In this post, we will explore the @ operator.

In [1]:
import numpy as np
In [2]:
A = np.matrix('3 1; 8 2')
A
Out[2]:
matrix([[3, 1],
        [8, 2]])
In [3]:
B = np.matrix('6 1; 7 9')
B
Out[3]:
matrix([[6, 1],
        [7, 9]])
In [4]:
A @ B
Out[4]:
matrix([[25, 12],
        [62, 26]])

Let's confirm this works

In [5]:
# element at the top left. i.e. (1, 1) aka (0, 0) in python
A[0, 0] * B[0, 0] + A[0, 1] * B[1, 0]
Out[5]:
25
In [6]:
# element at the top right. i.e. (1, 2) aka (0, 1) in python
A[0, 0] * B[0, 1] + A[0, 1] * B[1, 1]
Out[6]:
12
In [7]:
# element at the bottom left. i.e. (2, 1) aka (1, 0) in python
A[1, 0] * B[0, 0] + A[1, 1] * B[1, 0]
Out[7]:
62
In [8]:
# element at the top right. i.e. (2, 2) aka (1, 1) in python
A[1, 0] * B[0, 1] + A[1, 1] * B[1, 1]
Out[8]:
26
In [9]:
# let's put it in matrix form
result = np.matrix([[A[0, 0] * B[0, 0] + A[0, 1] * B[1, 0], A[0, 0] * B[0, 1] + A[0, 1] * B[1, 1]],
                    [A[1, 0] * B[0, 0] + A[1, 1] * B[1, 0], A[1, 0] * B[0, 1] + A[1, 1] * B[1, 1]]])
result
Out[9]:
matrix([[25, 12],
        [62, 26]])
In [10]:
A @ B == result
Out[10]:
matrix([[ True,  True],
        [ True,  True]], dtype=bool)

Looks good!

The Python Data Model specifies that the @ operator invokes __matmul__ and __rmatmul__.

We can overload @ by defining custom behavior for each of the special methods above, but this would result in our API not being Pythonic.

To build Pythonic objects, observe how real Python objects behave.


 
    
 
 

Comments