Skip to article frontmatterSkip to article content

6.2 Determinants

Dept. of Electrical and Systems Engineering
University of Pennsylvania

Binder

Lecture notes

1Reading

Material related to this page, as well as additional exercises, can be found in ALA 1.9.

2Learning Objectives

By the end of this page, you should know:

  • some key facts of the determinant,
  • several ways to find the determinant of a matrix,
  • (optional) the formal definition of a determinant.

3Determinants

We assume that you have already seen determinants in Math 1410, and focus here on reviewing the key properties. Before proceeding, we pause to note that determinants have very deep meanings, especially in differential calculus, as they keep track of volumes as they are transformed via (linear or otherwise) functions. They are indeed very useful theoretical tools, but much like matrix inverses, are rarely computed by hand, except for 2×22 \times 2 cases. Below is a helpful link if you need a refresher on the determinant.

3.1Key Properties of the Determinant

First, we’ll state a couple of key facts about the determinant.

These facts (and more) are all derivable from a basic principles of the determinant, but, as with many other topics in mathematics, the rabbit hole goes incredibly deep. For the purpose of studying eigenvalues and eigenvectors this is all we need, but for sake of completeness we included the rest of this page as further information on determinants.

3.2Optional: An Algebraic Definition of the Determinant

As mentioned above, we don’t really spend much time working with determinants in this course aside from for computing eigenvalues/vectors. However, for interested students, we will give an algebraic definition of the determinant as well as some methods of finding the determinant of a matrix. This definition is taken from these notes, which explain the connection between the geometric and algebraic interpretations of the determinant.

From this definition, we can compute the determinants of the elementary matrices!

To see why, note that the determinants of scaling and switching follow immediately from the multilinear and alternating properties of the determinant, respectively. To prove that the determinant of a row addition matrix is 1, we’ll show this is the case for a specific elementary matrix, and then you should convince yourself this is true for all row addition matrices:

det[100210001]=det[100010001]+det[000210001](multilinearity)=1+[000210001](determinant of identity is 1)=1+2[000110001](multilinearity)\begin{align*} \det \bm 1&0&0\\2&1&0\\0&0&1\em &= \det \bm 1&0&0\\0&1&0\\0&0&1\em + \det \bm 0&0&0\\2&1&0\\0&0&1\em \quad\text{(multilinearity)}\\ &= 1 + \bm 0&0&0\\2&1&0\\0&0&1\em \quad\text{(determinant of identity is $1$)}\\ &= 1 + 2\bm 0&0&0\\1&1&0\\0&0&1\em \quad\text{(multilinearity)}\\ \end{align*}

Using the alternating property, you can show that det[000110001]=0\det \bm 0&0&0\\1&1&0\\0&0&1\em = 0. Therefore, we have that det[100210001]=1\det \bm 1&0&0\\2&1&0\\0&0&1\em = 1.

Equipped with these results, we can see how right multiplying by an elementary matrix changes the determinant. Recall that right multiplication by an elementary matrix defines a column operation; we’ll also extend these results to left multiplication by an elementary matrix (which defines a row operation).

The proof of these properties is not hard, and follows from a few applications of the defining properties of the determinant. Try to prove these yourself!

Now, we are ready to prove a lot of useful facts about determinants! We’ll state and prove them one by one.

To prove this theorem, start by proving it for just upper triangular matrices UU with all nonzero pivots. Try to come up with a series of row addition operations to reduce UU to diagonal form, and then apply multilinearity to easily find the determinant of a diagonal matrix!

The case where UU has a zero on its diagonal is trickier. One way is to show that you can come up with a series of row addition and column scaling operations to reduce UU to a form with two identical columns, then apply the alternating property of the determinant to prove that UU must have zero determinant!

Next, we’ll state and prove the key property of the determinant used for computing eigenvalues.

To prove this statement, we’ll use the row echelon form of a matrix, in combination with our result on triangular matrices (recall that any matrix can be written as a product of elementary matrices followed by a matrix in row echelon form):

  • If AA is singular, then its row echelon form will have a zero on its diagonal. By our result on triangular matices, this implies that detA=0\det A = 0 (since row echelon matrices are triangular).

  • If AA is nonsingular, then its row echelon will have nn nonzero pivots (which must be diagonal elements). By our result on triangular matrices, and the fact that the product of nonzero numbers is nonzero, this implies that detA0\det A \neq 0.

Next, we’ll prove another extremely important property of determinants!

First, we’ll prove that this holds for invertible matrices. To prove this, recall that any invertible square matrix can be factored as a product of elementary matrices:

A=E1E2EmB=F1F2Fn\begin{align*} A &= E_1E_2 \dots E_m\\ B &= F_1F_2\dots F_n \end{align*}

Then, we can cleverly use our knowledge of how elementary operations change the determinant:

detAB=det(E1E2EmF1F2Fn)=detE1detE2detEmdetF1detF2Fn=det(E1E2Em)det(F1F2Fn)=detAdetB\begin{align*} \det AB &= \det (E_1E_2 \dots E_mF_1F_2\dots F_n) \\ &= \det E_1 \det E_2 \dots \det E_m \det F_1 \det F_2 \dots F_n\\ &= \det (E_1 E_2 \dots E_m) \det (F_1 F_2 \dots F_n)\\ &= \det A \det B \end{align*}

Next, we’ll consider the case where AA or BB, or both, is noninvertible. In this case, the result follows easily because a matrix product with a noninvertible factor is also noninvertible, and thus has zero determinant.

Try to prove this yourself! As a start, observe from the determinants of elementary matrices that transposing an elementary matrix does not change its determinant. Then, just like we did for matrix products, either write AA and AA^\top as products of elementary matrices or show that AA is noninvertible.

To prove this, start from the condition that AA1=IAA^{-1} = I, then apply this theorem!

Try to prove this yourself using the properties we have already proven!

3.3Optional: Methods of Computing the Determinant

In the section, we will review/introduce two way of computing the determinant: the Laplace expansion and the PLU-factorization.

This is quite an abstract definition, so let’s see it at work!

Note that in the Laplace expansion, the row or column chosen to compute the expansion is arbitrary! Thus, it makes sense to expand along rows and columns with lots of zeros; if the coefficient multiplying a submatrix determinant is zero, then we don’t have to actually compute that submatrix determinant!

For small matrices, the Laplace expansion works fine. However, for larger matrices (even with n10n \geq 10), this method of naively applying the Laplace will require a HUGE number of addition and multiplication operations (on the order of n!n!, or nn factorial)!

However, by applying our results for triangular matrices, we can come up with a much more computationally efficient method for computing the determinant.

Python Break!

Below are 3 code snippets demonstrating a few ways to compute the determinant. First, we run an implementation of the Laplace expansion (taken from this article). Second, we implement a determinant function based on the PLU factorization. Finally, we show how to use the built in determinant function from the scipy.linalg library.

import numpy as np
from scipy import linalg
import time

np.random.seed(2030)

# This code is from https://en.wikipedia.org/wiki/Laplace_expansion#Computational_expense
def laplace_det(M):
    # Base case of recursive function: 1x1 matrix
    if M.shape[0] == 1: 
        return M[0, 0]

    total = 0
    for column, element in enumerate(M[0]):
        # Exclude first row and current column.
        K = np.stack([np.concatenate((x[:column], x[column + 1 :]), axis=0) for x in M[1:]], axis=1)
        s = 1 if column % 2 == 0 else -1 
        total += s * element * laplace_det(K)
    return total

# Generate a random matrix
A = np.random.rand(9, 9) 
B = np.random.rand(10, 10)

# Find the determinant of A and B using Laplace expansion; also time how long it takes
start_time_A = time.time()
det_A = laplace_det(A)
end_time_A = time.time()

start_time_B = time.time()
det_B = laplace_det(B)
end_time_B = time.time()

print(f"Determinant (for 9x9): {det_A}")
print(f"Elapsed time (for 9x9): {end_time_A - start_time_A} seconds")
print(f"Determinant (for 10x10): {det_B}")
print(f"Elapsed time (for 10x10): {end_time_B - start_time_B} seconds")
Determinant (for 9x9): -0.007502281817950991
Elapsed time (for 9x9): 4.375511169433594 seconds
Determinant (for 10x10): -0.0334246928386742
Elapsed time (for 10x10): 40.4918212890625 seconds

Above is a recursive implementation of the Laplace expansion. As you can see, this implementation isn’t very fast! On this specific machine, it took ~4s to find the determinant for a 9×99\times 9 matrix; and ~40s to find the determinant for a 10×1010\times 10 matrix!

For anything longer, this implementation will take forever to finish. Luckily, using our linear algebra knowledge, we can give a much more efficient implementation of the determinant!

import numpy as np
from scipy import linalg
import time

np.random.seed(2030)

def sign(P):
    sign = 1
    visited = [0 for _ in range(len(P))]
    for i in range(len(P)):
        if visited[i] == 1:
            continue
        if P[i] == i:
            continue
        curr = P[i]
        visited[curr] = 1
        cycle_length = 1
        while curr != i:
            curr = P[curr]
            visited[curr] = 1
            cycle_length += 1
        if cycle_length % 2 == 0:
            sign = -sign
    return sign

def plu_det(M):
    P, L, U = linalg.lu(M, p_indices=True)
    return sign(P) * np.prod(np.diag(L)) * np.prod(np.diag(U))

# Generate a random matrix
A = np.random.rand(9, 9) 
B = np.random.rand(10, 10)

# Find the determinant of A and B using Laplace expansion; also time how long it takes
start_time_A = time.time()
det_A = plu_det(A)
end_time_A = time.time()

start_time_B = time.time()
det_B = plu_det(B)
end_time_B = time.time()

print(f"Determinant (for 9x9): {det_A}")
print(f"Elapsed time (for 9x9): {end_time_A - start_time_A} seconds")
print(f"Determinant (for 10x10): {det_B}")
print(f"Elapsed time (for 10x10): {end_time_B - start_time_B} seconds")
Determinant (for 9x9): -0.007502281817951028
Elapsed time (for 9x9): 0.0 seconds
Determinant (for 10x10): -0.033424692838674074
Elapsed time (for 10x10): 0.0 seconds

As you can see, with the PLU method, this method is much quicker; as you can see, for smaller matrices it was near instantaneous. A few notes; to find the PLU decomposition of AA, we used the scipy.linalg.lu function, which returns the LL and UU matrices, as well as either the PP matrix or its representation in one-line notation (this is because permutation matrices are mostly zeros, and can be encoded as just a list of numbers). Also, note the sign function we defined; the details aren’t important, but this function is essentially a fast way to compute the determinant of a permutation matrix given in one-line notation.

Finally, let’s see how to use the built in functions from scipy.linalg (or numpy.linalg) to find determinants!

import numpy as np
from scipy import linalg
import time

np.random.seed(2030)

# Generate a random matrix
A = np.random.rand(9, 9) 
B = np.random.rand(10, 10)

# Find the determinant of A and B using Laplace expansion; also time how long it takes
start_time_A = time.time()
det_A = linalg.det(A)
end_time_A = time.time()

start_time_B = time.time()
det_B = linalg.det(B)
end_time_B = time.time()

print(f"Determinant (for 9x9): {det_A}")
print(f"Elapsed time (for 9x9): {end_time_A - start_time_A} seconds")
print(f"Determinant (for 10x10): {det_B}")
print(f"Elapsed time (for 10x10): {end_time_B - start_time_B} seconds")
Determinant (for 9x9): -0.007502281817951028
Elapsed time (for 9x9): 0.0 seconds
Determinant (for 10x10): -0.033424692838674094
Elapsed time (for 10x10): 0.0 seconds

As you can see, it’s really easy, just a single call to the scipy.linalg.det function!

Binder