Skip to main content
Milestone #01Not StartedPhase 0Beginner8–12 hours · 1–2 weeks12 required tasks

Matrix Operations Engine

Build a pure-Python linear algebra library verified against NumPy

PythonNumPypytest
Build Progress0 / 12 tasks (0%)
0%(0/12 steps)Not Started
Project Specification & Architecture

What You Will Build

Every forward and backward pass in modern deep learning and Large Language Models is built on vector dot products, matrix transpositions, and matrix multiplications. Before relying on C++/CUDA-accelerated libraries like NumPy or PyTorch, you will implement a clean, reusable linear algebra library in pure Python from first principles. You will design explicit Vector and Matrix data structures, enforce strict shape invariants, implement O(n³) matrix multiplication with nested loops, and write an automated test suite comparing your outputs against NumPy within floating-point tolerances.

Why This Project Matters in the AI/LLM Stack

When debugging tensor shape mismatches in multi-head self-attention or backpropagation, engineers who have written matrix multiplication and transposition from scratch can immediately trace which inner dimensions must align and why incompatible shapes fail.

Learning Objectives

  • Design clean, immutable or well-validated Vector and Matrix classes in pure Python.
  • Enforce strict dimensionality checks and raise descriptive ValueError exceptions on shape mismatches.
  • Implement vector addition, scalar multiplication, dot products, matrix addition, transpose, and matrix multiplication without external libraries.
  • Verify numerical correctness across edge cases (rectangular, square, identity, and zero matrices) against NumPy.

Prerequisites

  • Core Python syntax: lists, nested loops, functions, classes, and custom exceptions
  • Basic understanding of 1D arrays (vectors) and 2D grids (matrices)

Required Mathematical Concepts

  • Vectors and vector dimensions (ℝⁿ)
  • Matrices and matrix dimensions (ℝᵐˣⁿ)
  • Elementwise addition, subtraction, and scalar multiplication
  • Inner (dot) product of two equal-length vectors
  • Matrix multiplication rule (Cᵢⱼ = ∑ₖ Aᵢₖ Bₖⱼ) and inner dimension compatibility
  • Matrix transposition ((Aᵀ)ᵢⱼ = Aⱼᵢ)
  • Floating-point precision and relative/absolute numerical tolerance
Interactive Engineering Checklist

Step-by-Step Implementation Tasks (12 Steps)

Check off each engineering task as your code passes its acceptance criteria. Progress is saved automatically in your browser.

Stage 1 of 40/2 tasks complete

Core Data Structures & Shape Validation

Define Vector and Matrix representations and validate row/column regularity.

Core

A reliable linear algebra library starts with clear representations for 1D vectors (`list[float]`) and 2D matrices (`list[list[float]]`) that expose `.shape` properties.

Implementation: Create `Vector` and `Matrix` classes (or structured types) in `linalg/core.py`. Store elements as floats, implement `__repr__`, `__len__`, indexing (`__getitem__`), and a `.shape` property returning `(n,)` for vectors and `(rows, cols)` for matrices.
Expected Outcome: Instantiating `Vector([1, 2, 3])` exposes `.shape == (3,)` and `Matrix([[1, 2], [3, 4]])` exposes `.shape == (2, 2)`.
Acceptance Check: Both classes defensive-copy input lists so mutating the caller's list does not corrupt internal matrix state.
Core

Jagged nested lists like `[[1, 2], [3]]` are not valid matrices and will cause index errors during multiplication.

Implementation: In `Matrix.__init__`, check that the input is non-empty, contains only numeric values (`int` or `float`), and that every row has the exact same length. Raise a descriptive `ValueError` if any row length differs.
Expected Outcome: Passing a ragged list `[[1, 2, 3], [4, 5]]` immediately raises `ValueError` with a message explaining the row length mismatch.
Acceptance Check: All invalid shapes (empty list `[]`, empty row `[[]]`, jagged rows) are rejected at construction time.
Stage 2 of 40/3 tasks complete

Vector Operations & Inner Products

Implement elementwise vector arithmetic, scalar scaling, and dot products.

Core

Vector addition combines two vectors of equal dimension component-by-component: `(u + v)_i = u_i + v_i`. It is used in bias addition and residual connections.

Implementation: Implement `vector_add(u: Vector, v: Vector) -> Vector` (and ` vector_sub`) in pure Python. Verify that `u.shape == v.shape` before summing corresponding elements.
Expected Outcome: `vector_add(Vector([1.0, -2.0, 3.5]), Vector([4.0, 2.0, 0.5]))` returns `Vector([5.0, 0.0, 4.0])`.
Acceptance Check: Adding two vectors of different lengths raises a `ValueError`.
Core

Multiplying a vector or matrix by a scalar `alpha` scales every entry by `alpha` without changing its dimensions.

Implementation: Implement `scalar_multiply_vector(alpha: float, v: Vector) -> Vector` and `scalar_multiply_matrix(alpha: float, m: Matrix) -> Matrix`.
Expected Outcome: Scaling `Matrix([[1, -2], [3, 0]])` by `2.5` returns `Matrix([[2.5, -5.0], [7.5, 0.0]])`.
Acceptance Check: Multiplying by `0.0` yields a zero vector/matrix of identical shape; multiplying by `1.0` preserves all entries.
Core

The dot product `u · v = ∑ u_i * v_i` measures alignment between two vectors and forms the core computation of every artificial neuron and matrix multiply.

Implementation: Implement `dot(u: Vector, v: Vector) -> float`. Validate equal lengths, multiply paired components, and return the accumulated float sum.
Expected Outcome: `dot(Vector([1, 3, -5]), Vector([4, -2, -1]))` returns `3.0`.
Acceptance Check: Orthogonal vectors return `0.0`; mismatched vector lengths raise `ValueError`.
Stage 3 of 40/4 tasks complete

Matrix Arithmetic, Transpose & Multiplication

Build 2D matrix addition, transposition, and pure-Python matrix multiplication with dimension guards.

Core

Two matrices `A` and `B` can be added or subtracted if and only if they have identical `(rows, cols)` dimensions.

Implementation: Implement `matrix_add(A: Matrix, B: Matrix) -> Matrix` and `matrix_sub(A: Matrix, B: Matrix) -> Matrix`. Check `A.shape == B.shape` and return a new `Matrix` containing the elementwise sum or difference.
Expected Outcome: Elementwise sum of two `(2, 3)` matrices produces a new `(2, 3)` matrix with exact sums.
Acceptance Check: Attempting to add a `(2, 3)` matrix and a `(3, 2)` matrix raises `ValueError`.
Core

Transposing an `(m, n)` matrix flips its rows and columns into an `(n, m)` matrix where `(Aᵀ)_{j,i} = A_{i,j}`.

Implementation: Implement `transpose(A: Matrix) -> Matrix` (and `.T` property). Ensure rectangular matrices of shape `(m, n)` become `(n, m)`.
Expected Outcome: Transposing a `(2, 4)` matrix yields a `(4, 2)` matrix; transposing twice `A.T.T` restores `A`.
Acceptance Check: Works for square `(n, n)`, row `(1, n)`, and column `(n, 1)` matrices.
Intermediate

For `A` of shape `(m, k)` and `B` of shape `(k, n)`, entry `(i, j)` of `C = A @ B` is the dot product of row `i` of `A` with column `j` of `B`, producing an `(m, n)` matrix.

Implementation: Implement `matmul(A: Matrix, B: Matrix) -> Matrix` using pure Python loops (no NumPy). Pre-transpose `B` or iterate over `i in range(m)`, `j in range(n)`, `p in range(k)` to compute each entry.
Expected Outcome: Multiplying a `(3, 4)` matrix by a `(4, 2)` matrix produces the exact `(3, 2)` product matrix.
Acceptance Check: Multiplying any matrix `A` by the appropriate identity matrix `I` returns `A` unchanged.
Core

Clear dimension error messages save hours of debugging when chaining linear transformations.

Implementation: Audit all vector and matrix operations (`vector_add`, `dot`, `matrix_add`, `matmul`) so that any shape mismatch raises a `ValueError` that includes both actual shapes in the error string (e.g., `Cannot multiply (2, 3) by (2, 3): inner dimensions 3 != 2`).
Expected Outcome: Every invalid operation raises a descriptive `ValueError` instead of a generic `IndexError`.
Acceptance Check: Unit tests explicitly assert that `pytest.raises(ValueError)` triggers on incompatible shapes.
Stage 4 of 40/3 tasks complete

NumPy Verification, Unit Testing & Documentation

Verify outputs against NumPy, build a comprehensive pytest suite, and document your API.

Core

Floating-point arithmetic can differ by ~1e-15 due to operation ordering. Comparing against `numpy` with `np.allclose` validates numerical accuracy.

Implementation: Write a verification helper `verify_against_numpy()` that generates random rectangular, square, identity, and zero matrices, runs your pure-Python operations, and compares the output against `np.dot`, `np.matmul`, and `.T` using `np.testing.assert_allclose(..., rtol=1e-6, atol=1e-8)`.
Expected Outcome: 100% of randomized and edge-case comparisons match NumPy within `1e-6` relative tolerance.
Acceptance Check: NumPy is imported only inside test/verification files, keeping the core library 100% pure Python.
Core

A structured test suite ensures edge cases remain unbroken as you extend your library.

Implementation: Create `tests/test_linalg.py` using `pytest`. Include tests for rectangular `(2, 5) @ (5, 3)`, square `(4, 4)`, identity `I_n`, zero matrices, negative numbers, and invalid dimension exceptions.
Expected Outcome: Running `pytest` executes all test cases with 0 failures.
Acceptance Check: At least 12 distinct test functions covering valid math, boundary shapes `(1, 1)`, and shape errors.
Core

Clear docstrings and complexity notes make your library reusable in later phases.

Implementation: Add type annotations, docstrings specifying input/output shapes and time complexity (`O(n)` for dot product, `O(m·k·n)` for matmul), and a `README.md` showing usage examples and benchmark comparisons against NumPy.
Expected Outcome: A complete, well-documented Python package with usage examples and complexity analysis.
Acceptance Check: `README.md` includes installation/test instructions and a brief explanation of why vectorized C buffers in NumPy outperform pure Python loops.
Reference Architecture & Verification Code

Starter & Verification Code Examples

Shape Validation & Pure-Python Matrix Multiplication Skeleton

Demonstrates how to validate 2D matrix regularity and structure the inner dimension check for matrix multiplication.

class Matrix:
    def __init__(self, rows: list[list[float]]) -> None:
        if not rows or not rows[0]:
            raise ValueError("Matrix must contain at least one non-empty row.")
        num_cols = len(rows[0])
        cleaned: list[list[float]] = []
        for r_idx, row in enumerate(rows):
            if len(row) != num_cols:
                raise ValueError(
                    f"Row {r_idx} has length {len(row)}, expected {num_cols}."
                )
            cleaned.append([float(val) for val in row])
        self._data = cleaned
        self.shape = (len(cleaned), num_cols)

    def matmul(self, other: "Matrix") -> "Matrix":
        m, k1 = self.shape
        k2, n = other.shape
        if k1 != k2:
            raise ValueError(
                f"Incompatible shapes for matmul: {self.shape} and {other.shape} (inner dims {k1} != {k2})"
            )
        # Compute C[i][j] = sum_p A[i][p] * B[p][j]
        result = [
            [
                sum(self._data[i][p] * other._data[p][j] for p in range(k1))
                for j in range(n)
            ]
            for i in range(m)
        ]
        return Matrix(result)
Verification & Acceptance Suite

How to Test Your Implementation

Run your pytest suite to verify algebraic identities, shape error handling, and floating-point equivalence against NumPy.

$ pytest tests/test_linalg.py -vTest Runner

Identity Matrix Multiplication Invariant

Verify that multiplying an (m, n) matrix A by I_n on the right and I_m on the left returns A.

Steps: Construct a (3, 5) matrix A and 5x5 identity matrix I_5. Compute matmul(A, I_5) and assert equality with A.

Pass Criteria: Output shape is (3, 5) and all elements exactly equal A.

Incompatible Inner Dimensions Guard

Confirm that matmul((2, 3), (2, 3)) fails cleanly before partial computation.

Steps: Call matmul(Matrix([[1, 2, 3], [4, 5, 6]]), Matrix([[1, 2, 3], [4, 5, 6]])) inside pytest.raises(ValueError).

Pass Criteria: Raises ValueError mentioning inner dimensions 3 and 2.

Rectangular Matrix Multiplication vs NumPy

Validate triple-loop indexing on non-square dimensions (4, 7) @ (7, 2).

Steps: Generate random floats for A (4, 7) and B (7, 2), compute matmul(A, B), and compare with np.matmul(A_np, B_np).

Pass Criteria: Maximum absolute difference < 1e-12.

Overall Project Acceptance Criteria

  • Correct results for all valid vector and matrix input shapes.
  • Clear, descriptive ValueError exceptions raised for any incompatible shapes.
  • Automated unit tests covering rectangular, square, identity, and zero matrices.
  • Numerical verification against NumPy passing with `np.testing.assert_allclose`.
Progressive Spoiler-Free Guidance

Expandable Hints & Debugging Tips

Try implementing each stage on your own first. Expand a hint below if you want to verify tensor shapes, mathematical identities, or common edge cases.

Optional Bonus Extensions

Optional Stretch Challenges

Optional · Does Not Block Completion

Support Batched 3D Matrix Multiplication

Extend your engine to multiply batched 3D tensors of shape (B, M, K) and (B, K, N) producing (B, M, N), mirroring how Transformer attention processes batches of sequences.

What You Learn: How batch dimensions wrap standard 2D linear algebra operations in deep learning.

Vector Norms & Cosine Similarity

Implement L1 norm, L2 Euclidean norm, and cosine similarity `cos(θ) = (u · v) / (||u||_2 ||v||_2)` with zero-norm guards.

What You Learn: How embedding similarity search and vector databases compare semantic representations.

Expected Deliverable

What Your Completed Repository Should Contain

A reusable Python matrix operations library.

Deliverable Artifacts

  • Pure-Python `linalg` module with `Vector` and `Matrix` classes
  • Automated `pytest` verification suite comparing outputs with NumPy
  • README documentation with API examples and complexity analysis

After Completing This Project, You Should Be Able To...

  • Implement vector addition, scalar multiplication, dot products, transposes, and matrix multiplication from scratch in pure Python.
  • Predict output dimensions and diagnose shape mismatches across chained linear transformations.
  • Write automated numerical unit tests using floating-point tolerances against a reference library.
  • Explain why contiguous C memory buffers in NumPy outperform pure-Python nested loops.
Portfolio & Repository Tracking

GitHub Repository Submission

Link your public or private GitHub repository URL to keep a structured portfolio of your from-scratch AI builds. Stored locally in your browser (self-reported; no GitHub tokens or remote code execution).

Status: Not Linked

Suggested Repository: matrix-operations-engine

Recommended Directory Layout:

linalg/__init__.py
linalg/core.py
tests/test_linalg.py
README.md

Recommended README Documentation Checklist

  • Overview of implemented vector and matrix operations
  • How to run the pytest verification suite against NumPy
  • Time complexity table and pure-Python vs NumPy timing comparison
Local Engineering Notebook

Personal Implementation Notes