Some stock functions

On this page we’re going to define some stock functions. If you don’t care about the details and want to skip ahead to actually using some of them, just read the summary at the end so you know what they’re for as we continue. We’ll rush through these because they’re fairly trivial code, and will spend more time on others later.

subtract()

The subtract function is actually identical to the add function except for the obvious change:

def subtract(matrix1, matrix2):
row_range = range(rows(matrix1))
col_range = range(columns(matrix1))
return [[matrix1[i][j] - matrix2[i][j] for j in col_range] for i in row_range]


I don’t think much explanation is required here. It’s simply an element-wise subtraction of matrix2 from matrix1.

zeroes()

We will often find it useful to create a matrix of a given size, initially ‘blank’, or populated by zeroes. This is achieved simply enough.

def zeroes(num_rows, num_cols=-1):
if num_cols == -1:
count_rows = range(num_rows)
return [[0 for i in count_rows] for i in count_rows]
else:
count_rows = range(num_rows)
count_cols = range(num_cols)
return [[0 for i in count_cols] for j in count_rows]


Declaring num_cols=-1 in the function signature is how we tell Python that this is an optional parameter. If it is not specified when the function is called, it gets the default value of -1 (or whatever we choose). If we call zeroes(5), then we get a square matrix with the same number of rows as columns, that is five. If we call zeroes(5,3), then we get a rectangular matrix with five rows and three columns.

ones()

Same as above, sometimes we want a matrix populated by 1s. The function is again identical except for the obvious change.

def ones(num_rows, num_cols=-1):
if num_cols == -1:
count_rows = range(num_rows)
return [[1 for i in count_rows] for i in count_rows]
else:
count_rows = range(num_rows)
count_cols = range(num_cols)
return [[1 for i in count_cols] for j in count_rows]


eye()

Most linear algebra packages have a function called eye(), and it does the same here as elsewhere. Linear algebra features what is called an identity matrix, and it is to matrices as the number 1 is to other numbers: multiplying any matrix by the identity returns the same matrix, or said another way, does nothing. If $$I_n$$ is the identity matrix of size $$n$$, and $$A$$ is a matrix of size ($$n$$, anything), then $$I_nA = A.$$Usually we will be dealing with square matrices $$A$$ in which case the statement $$A=AI_n$$is also true. For non-square $$A$$ these are not both true at the same time. The identity matrix is just a matrix of zeroes, except for the entries on the leading diagonal, which are equal to one. In other words, something like $$I_3 = \begin{bmatrix}1&0&0\\0&1&0\\0&0&1\end{bmatrix}.$$ The function definition which reproduces this is

def eye(size):
size = range(size)
return [[1 if i == j else 0 for i in size] for j in size]


This marks the first time we’ve used an if statement inside a list comprehension. It uses what is called a ternary operator, which are variously loved and loathed by programmers, but I like them, and they’re necessary if we’re going to use list comprehensions. The syntax is $$\textrm{(statement1) if (condition) else (statement2).}$$ So the first statement is executed if the condition is true, and if the condition is false the second statement is executed. In English, “do this if the condition is true, otherwise do that”. Here, we get the result we want: the matrix elements are equal to one only where the row and column indices match, and are equal to zero otherwise.

scalar_matrix()

Multiplying a matrix by a scalar number is a very common operation, and it’s very easy to do. Simply multiply every element of the matrix by the same scalar value. In Python,

def scalar_matrix(scalar, matrix):
count_cols = range(columns(matrix))
count_rows = range(rows(matrix))
return [[scalar*matrix[i][j] for j in count_cols] for i in count_rows]


This is not dissimilar to our function declarations for add() and subtract(), so I think it’s clear enough what’s happening. The returned matrix is simply the product of the scalar with each element of the original matrix.

Summary

So far our functional repertoire is:

• rows(matrix): count the number of rows in a matrix.
• columns(matrix): count the number of columns in a matrix.
• add(matrix1, matrix2): compute the element-wise sum of two matrices.
• subtract(matrix1, matrix2): compute the element-wise difference of two matrices.
• zeroes(num_rows, num_cols=-1): generate a matrix of the given size filled with zeroes.
• ones(num_rows, num_cols=-1): generate a matrix of the given size filled with ones.
• eye(size): generate a square identity matrix of the given size.
• scalar_matrix(scalar, matrix): compute the product of a scalar value and a matrix.