A Python Matrix class implementing linear-algebra operations: matrix
classification, trace, transpose, addition/subtraction, product, determinant and
cofactors.
main.py— theMatrixclass (all static methods).run.py— entry point: importsMatrixand runs a demo.
python3 run.py- What is a matrix?
- Notation
- Types of matrices
- Transpose
- Trace
- Operations
- Elementary transformations
- Determinant
- Matrix inverse
- Map: theory → code
Matrices and determinants are linear-algebra tools that make it easier to organize and manipulate data.
A matrix is a two-dimensional array (table) of numbers — abstract quantities that can be added, subtracted and multiplied. Formally, its entries are elements of a ring.
They are used to describe systems of linear equations and to record data that depends on several parameters.
Applications: computing (images/pixels), robotics (rotating robotic arms), graphics, equation systems, and more.
A matrix is laid out by rows (m) and columns (n); it is called an
m×n matrix (m rows by n columns). Each entry is denoted a(i,j): the first
subscript i is the row, the second j is the column (rows first, then columns).
Shorthand: A = (a_ij).
n = columns →
┌ ┐
m │ a11 a12 a13 │
= │ a21 a22 a23 │ dimension: m × n
rows │ a31 a32 a33 │
↓ └ ┘
Example on a 3×4 matrix: b11 = 1, b23 = 0, b13 = -5.
In code,
Matrix.size(mtx)returns the dimension as a tuple(m, n), andMatrix.check(mtx)validates that every row has the same length.
| Type | Condition | Method |
|---|---|---|
| Row | A single row: 1×n (e.g. 1×3, 1×7) |
Matrix.row_type |
| Column | A single column: m×1 (e.g. 2×1, 4×1) |
Matrix.column_type |
| Square | Same number of rows and columns: n×n |
Matrix.square_type |
In a square matrix we distinguish the main diagonal (a11, a22, a33, …) and
the secondary diagonal (top-right → bottom-left).
| Type | Condition | Method |
|---|---|---|
| Null | All entries are 0 | Matrix.null_type |
| Diagonal | Only the main diagonal is non-zero; the rest are 0 | Matrix.diagonal_type |
| Scalar | A diagonal matrix whose diagonal entries are all equal | Matrix.scale_type |
Identity (I) |
A scalar matrix whose diagonal is all 1s | Matrix.identity_type |
| Triangular | A triangle of 0s above (lower) or below (upper) the diagonal | Matrix.triangular_type |
| Row echelon | Each row's first non-zero entry (pivot) sits to the right of the previous row's pivot | Matrix.step_type |
- Scalar matrix: multiplying another matrix by a scalar matrix equals multiplying it by that single diagonal number.
- Identity matrix: multiplying any matrix by
Ireturns the same matrix (multiplicative neutral element). - Upper triangular: all entries below the main diagonal are 0. Lower triangular: all entries above the main diagonal are 0.
Swaps rows for columns: the 1st row becomes the 1st column, the 2nd row the 2nd
column, and so on. Main-diagonal entries stay put; the rest are swapped. Method:
Matrix.traspuesta.
The trace of a matrix is the sum of its main-diagonal entries:
Trace(A) = a11 + a22 + a33 + … + a_mn
Method: Matrix.traza.
- Add/subtract each entry with the entry in the same position of the other matrix.
- Only matrices of the same dimension can be added/subtracted.
- The result keeps those dimensions.
Methods: Matrix.sum, Matrix.resta.
- Every entry of the matrix is multiplied by the scalar (any number).
- The result keeps its dimensions.
(m × n) * (n × p) = (m × p)
- Two matrices can be multiplied only when the number of columns of the first
(
n) matches the number of rows of the second (n). - The result has dimension
m × p(rows of the first × columns of the second). - Not commutative:
A * B ≠ B * A.
Each entry of the result is the sum of the products of row i of the first matrix
by column j of the second. Example with mtx1 (2×4) and mtx2 (4×3), as run by
run.py:
mtx1 = [[ 2, -2, 3, 0], mtx2 = [[ 1, -3, 6],
[-1, 0, 2, 4]] [ 2, 4, 0],
[ 3, 7, -1],
[ 0, 9, 1]]
Row 1 · Col 1 → a11 = (2·1)+(-2·2)+(3·3)+(0·0) = 7
Row 1 · Col 2 → a12 = (2·-3)+(-2·4)+(3·7)+(0·9) = 7
Row 1 · Col 3 → a13 = (2·6)+(-2·0)+(3·-1)+(0·1) = 9
Row 2 · Col 1 → a21 = (-1·1)+(0·2)+(2·3)+(4·0) = 5
Row 2 · Col 2 → a22 = (-1·-3)+(0·4)+(2·7)+(4·9) = 53
Row 2 · Col 3 → a23 = (-1·6)+(0·0)+(2·-1)+(4·1) = -4
mtx1 * mtx2 = [[ 7, 7, 9],
[ 5, 53, -4]]
Method: Matrix.multiply (supports matrix×matrix and matrix×scalar in any order).
There is no direct matrix division: you divide by multiplying by the inverse. See Matrix inverse. (Not yet implemented in code.)
Valid transformations inside a matrix:
- Swap two lines (rows or columns).
- Multiply or divide a line by a number
≠ 0. - Replace a line by a linear combination of other lines.
The determinant of a matrix is a scalar that represents the matrix's singularity. It is defined only for square matrices.
Applications:
- Solving equation systems via determinants.
- Telling whether a matrix is invertible (if
|M| = 0,Mis not invertible). - Telling whether a set of
nvectors is linearly dependent.
Method: Matrix.determinante.
Product of the main diagonal minus product of the secondary diagonal:
| a b |
| c d | = (a·d) − (b·c)
Sarrus' rule. Two equivalent variants (they pick the same groups of entries):
- Variant 1 (bounce effect): multiply the main diagonal and its associated triangles and sum them; subtract the same computation done over the secondary diagonal.
- Variant 2: copy the first rows below the matrix, trace three lines along the main diagonal (products that are summed) and three along the secondary diagonal (products that are subtracted).
- Swapping two consecutive lines (rows or columns) flips the sign of the determinant. (For non-consecutive lines, do it step by step.)
- Replacing a line by a linear combination with other lines leaves the determinant unchanged.
- The determinant can be split into a sum of two others if all lines are equal except one.
- The determinant of the transpose is unchanged:
|A| = |Aᵀ|. - The determinant of the inverse is the inverse of the determinant:
|A⁻¹| = 1 / |A|(e.g.|A| = 27 → |A⁻¹| = 1/27). - A common factor in a line multiplies the determinant.
- The determinant of a product is the product of the determinants:
|A·B| = |A| · |B|.
When |A| = 0, some line of the matrix is problematic: it is equal, proportional
to, or a linear combination of another. In a linear system this means there are
equal/proportional equations or a contradictory one, and the system cannot be
solved because that row carries no independent information.
The determinant is 0 if:
- there is a row/column of zeros;
- there are two equal parallel lines;
- there are two proportional parallel lines;
- one line is a linear combination of the others.
In code this is stubbed in
Matrix.det0Condition(currently always returnsFalse; not yet implemented).
The cofactor of an entry a_ij is the determinant of the entries left after
deleting the row and column of a_ij, signed by the parity of i+j:
- if
i + jis even → keep the sign; - if
i + jis odd → flip the sign.
a13 → 1+3 = 4 (even) → keep
a13 → 2+1 = 3 (odd) → flip
a23 → 3+2 = 5 (odd) → flip
Method: Matrix.adjunt(mtx, (i, j)). (Remember indices start at 0.)
Given a matrix, its cofactor matrix replaces every entry by its cofactor.
Method: Matrix.adjunt(mtx) (with no second argument).
Expansion along the entries of a row or column (Laplace):
- Pick any line (preferably the one with the most zeros, to simplify).
- Multiply each entry of that line by its cofactor.
- Sum everything.
If an entry is 0, its term vanishes (0 · cofactor) and need not be computed.
Dividing matrices means multiplying by the inverse.
Properties:
- A matrix times its inverse is the identity:
A · A⁻¹ = I. - Here it is commutative:
A · A⁻¹ = A⁻¹ · A = I. - The inverse of the transpose equals the transpose of the inverse:
(Aᵀ)⁻¹ = (A⁻¹)ᵀ. - The inverse of the inverse is the original matrix:
(A⁻¹)⁻¹ = A. - The inverse of a product reverses the order:
(A·B)⁻¹ = B⁻¹ · A⁻¹(because the product is not commutative).
Variant 1 — Formula: uses the determinant and the cofactor matrix. If
|A| = 0, A has no inverse (division by zero is not allowed). Compute the
determinant first to check existence.
Variant 2 — Gauss-Jordan: append the identity to the right (with a separating
bar) and apply transformations to A until the left side becomes the identity; the
right side is then A⁻¹. The same transformations apply to both sides.
Recommended: use the formula for small matrices and Gauss-Jordan for large ones. (Inverse not yet implemented in code.)
| Concept | Method in main.py |
|---|---|
Dimension (m, n) |
Matrix.size |
| Validate uniform rows | Matrix.check |
| Types by shape | row_type, column_type, square_type |
| Types by elements | null_type, diagonal_type, scale_type, identity_type, triangular_type, step_type |
| Diagonals | leftDiagonal, rightDiagonal |
| Trace | traza |
| Transpose | traspuesta |
| Add / subtract | sum, resta |
| Product (matrix/scalar) | multiply |
| Determinant | determinante |
| Cofactor / adjugate | adjunt |
| Utilities | create, duplicate, extend, staticReduce, pivotReduce |
| Division / inverse | not yet implemented |
Created by @albertolicea00