SigmaField
Mathematical Foundations for Quant Finance
0 of 256 lessons
      1. 3.6.1 Eigenvalues and eigenvectorsConcept · 35 min
      2. 3.6.2 Diagonalisation and matrix powersConcept · 30 min
      3. 3.6.3 Symmetric matrices and the spectral theoremConcept · 30 min
      4. 3.6.4 Practice set: eigenvaluesPractice set · 20 min
      5. 3.6.5 Case study: principal components of the yield curveCase study · 35 min

Level 3, Linear algebra 3.6 Eigenvalues and eigenvectors Lesson 4 of 5

Practice setLesson 3.6.4 in Level 3, Linear algebra. About 20 minutes.

Practice set: eigenvalues

Eigenvalues and eigenvectors

Eigenvalues and eigenvectors (lesson 3.6.1)

0 of 7 correct

  1. 1.
  2. 2.
  3. 3.
  4. 4.
  5. 5.
  6. 6.
  7. 7.
How to type answers
  • Powers with ^: x^7, 2^(1/3), a^-2.
  • Multiply with * or by writing side by side: 3x^2, 2(x+1).
  • ln(x) is the natural log, log(x, 2) is log base 2, e is Euler's number, sqrt(x) is a square root.
  • sin(x), cos(x) and tan(x) take radians; write pi for π and sin(x)^2 for sin²x.
  • Your first answer to each question is saved: it counts towards your score and brings the question back for review.
  • Exact answers like ln(20)/ln(3) are best. Decimals need about 4 significant figures.

Diagonalisation and powers

Diagonalisation and matrix powers (lesson 3.6.2)

0 of 7 correct

  1. 1.
  2. 2.
  3. 3.
  4. 4.
  5. 5.
  6. 6.
  7. 7.
How to type answers
  • Powers with ^: x^7, 2^(1/3), a^-2.
  • Multiply with * or by writing side by side: 3x^2, 2(x+1).
  • ln(x) is the natural log, log(x, 2) is log base 2, e is Euler's number, sqrt(x) is a square root.
  • sin(x), cos(x) and tan(x) take radians; write pi for π and sin(x)^2 for sin²x.
  • Your first answer to each question is saved: it counts towards your score and brings the question back for review.
  • Exact answers like ln(20)/ln(3) are best. Decimals need about 4 significant figures.

Symmetric matrices

Symmetric matrices and the spectral theorem (lesson 3.6.3)

0 of 7 correct

  1. 1.
  2. 2.
  3. 3.
  4. 4.
  5. 5.
  6. 6.
  7. 7.
How to type answers
  • Powers with ^: x^7, 2^(1/3), a^-2.
  • Multiply with * or by writing side by side: 3x^2, 2(x+1).
  • ln(x) is the natural log, log(x, 2) is log base 2, e is Euler's number, sqrt(x) is a square root.
  • sin(x), cos(x) and tan(x) take radians; write pi for π and sin(x)^2 for sin²x.
  • Your first answer to each question is saved: it counts towards your score and brings the question back for review.
  • Exact answers like ln(20)/ln(3) are best. Decimals need about 4 significant figures.

Coding exercise

Exercise

The power method

Write power_method(A, x0, tol=1e-10, max_steps=10_000) that returns (lam, v), as in lesson 3.6.2. lam is the eigenvalue of largest size of the square matrix A, and v a unit eigenvector for it.

  • Scale x0 to length 1. At each step compute y=Ax\mathbf{y} = A\mathbf{x} and the estimate λ=x⋅y\lambda = \mathbf{x} \cdot \mathbf{y}.
  • Stop when ∥y−λx∥\lVert \mathbf{y} - \lambda\mathbf{x} \rVert is below tol, which says Ax=λxA\mathbf{x} = \lambda\mathbf{x} to within tol. Otherwise set x=y/∥y∥\mathbf{x} = \mathbf{y} / \lVert \mathbf{y} \rVert and go on.
  • Return v with length 1 and its entry of largest size positive, so that the answer does not depend on the sign.
  • Raise ValueError if A is not square, or x0 is zero or has the wrong length. Raise RuntimeError after max_steps steps without stopping.

The tests include lesson 3.6.3's 3×33 \times 3 matrix, a dominant eigenvalue of −6-6, a start that A sends to 0\mathbf{0} and the quarter turn. A version that stops when x\mathbf{x} stops changing never stops for the −6-6: work out why before you run it.

See the tests
import numpy as np


def test_symmetric():
    """S = [[2, 1], [1, 2]] from (1, 0): λ = 3 and v = (1, 1)/√2"""
    lam, v = power_method([[2, 1], [1, 2]], [1, 0])
    expect_close(lam, 3.0, what="eigenvalue", rel=1e-9)
    expect_close(v, np.array([1, 1]) / np.sqrt(2), what="eigenvector", abs_tol=1e-6)


def test_not_symmetric():
    """Lesson 3.6.2's A = [[1, 2], [3, 2]] from (1, 0): λ = 4 and v = (2, 3)/√13"""
    lam, v = power_method([[1, 2], [3, 2]], [1, 0])
    expect_close(lam, 4.0, what="eigenvalue", rel=1e-9)
    expect_close(v, np.array([2, 3]) / np.sqrt(13), what="eigenvector", abs_tol=1e-6)


def test_steady_state():
    """The two towns, M = [[0.9, 0.2], [0.1, 0.8]]: λ = 1 and v = (2, 1)/√5"""
    lam, v = power_method([[0.9, 0.2], [0.1, 0.8]], [1, 0])
    expect_close(lam, 1.0, what="eigenvalue", rel=1e-9)
    expect_close(v, np.array([2, 1]) / np.sqrt(5), what="eigenvector", abs_tol=1e-6)


def test_three_by_three():
    """Lesson 3.6.3's B from (1, 0, 0): λ = 6 and v = (−1, 2, −1)/√6, its largest entry positive"""
    B = [[3, -1, 1], [-1, 5, -1], [1, -1, 3]]
    lam, v = power_method(B, [1, 0, 0])
    expect_close(lam, 6.0, what="eigenvalue", rel=1e-9)
    expect_close(v, np.array([-1, 2, -1]) / np.sqrt(6), what="eigenvector", abs_tol=1e-6)


def test_unit_length():
    """The eigenvector returned has length 1, whatever the length of x0"""
    _, v = power_method([[1, 2], [3, 2]], [100, 0])
    expect_close(float(np.linalg.norm(v)), 1.0, what="length of v", rel=1e-12)


def test_negative_eigenvalue():
    """[[−5, 2], [2, −2]] has λ = −6: x flips at every step, yet λ = −6 and v = (2, −1)/√5"""
    lam, v = power_method([[-5, 2], [2, -2]], [1, 0])
    expect_close(lam, -6.0, what="eigenvalue", rel=1e-9)
    expect_close(v, np.array([2, -1]) / np.sqrt(5), what="eigenvector", abs_tol=1e-6)


def test_slow():
    """[[1, 0.01], [0.01, 1]], with eigenvalues 1.01 and 0.99, still converges: λ = 1.01"""
    lam, _ = power_method([[1, 0.01], [0.01, 1]], [1, 0])
    expect_close(lam, 1.01, what="eigenvalue", rel=1e-9)


def test_zero_eigenvalue():
    """Z = [[1, 2], [0.5, 1]] sends x0 = (2, −1) to 0: λ = 0 and v = (2, −1)/√5"""
    lam, v = power_method([[1, 2], [0.5, 1]], [2, -1])
    expect_close(lam, 0.0, what="eigenvalue", abs_tol=1e-12)
    expect_close(v, np.array([2, -1]) / np.sqrt(5), what="eigenvector", abs_tol=1e-9)


def test_rotation():
    """A quarter turn keeps no direction: RuntimeError after max_steps"""
    try:
        power_method([[0, -1], [1, 0]], [1, 0], max_steps=500)
    except RuntimeError:
        return
    raise AssertionError("expected RuntimeError for the quarter turn, which has no real eigenvector")


def test_max_steps():
    """Five steps are not enough for S from (1, 0) at tol 1e-10: RuntimeError"""
    try:
        power_method([[2, 1], [1, 2]], [1, 0], max_steps=5)
    except RuntimeError:
        return
    raise AssertionError("expected RuntimeError after 5 steps")


def test_bad_inputs():
    """A 2 × 3 matrix, a zero start, or a start of the wrong length: ValueError"""
    for A, x0, what in [([[1, 2, 3], [4, 5, 6]], [1, 0, 0], "a 2 × 3 matrix"),
                        ([[2, 1], [1, 2]], [0, 0], "x0 = (0, 0)"),
                        ([[2, 1], [1, 2]], [1, 0, 0], "x0 with 3 entries for a 2 × 2 matrix")]:
        try:
            power_method(A, x0)
        except ValueError:
            continue
        raise AssertionError(f"expected ValueError for {what}")

Free further reading

Optional. This lesson covers what you need; these add more examples and practice. All are free to read.