A matrix is a rectangular array of numbers written between rectangular brackets, as in

$\begin{bmatrix} 0 & 1 & 5 \\ 4 & 7 & 9 \end{bmatrix}$

You can also use large parentheses

$\begin{pmatrix} 0 & 1 & 5 \\ 4 & 7 & 9 \\ 6 & 2 & 7 \end{pmatrix}$

All matrices have a size (or dimensions). This corresponds to the numbers of rows and columns. The first matrix above is a 2 x 2 matrix, and the second one is a 2 x 3 matrix. A matrix of size $$m \times n$$ is called an $$m \times n$$ matrix. The elements (or entries or coefficients) of a matrix are the values in the array. The $$i, j$$ element of a matrix is the value in the $$i$$th row and $$j$$th column, denoted by double subscripts, as in $$A_{ij}$$. The positive integers $$i$$ and $$j$$ are called (the row and column) indices. If $$A$$ is an $$m \times n$$ matrix, then the row index $$i$$ runs from 1 to $$m$$ and the column index $$j$$ runs from 1 to $$n$$. Row indices go from top to bottom, column indices go from left to right.

Two matrices are equal if they have the same size, and the corresponding entries are all equal. The set of real $$m \times n$$ matrices is denoted $$\mathbf{R}^{m \times n}$$. That’s because we normally deal with matrices with entries that are real numbers.

import numpy as np

A = np.array([[0, 1, 5], [4, 7, 9]])
A
## array([[0, 1, 5],
##        [4, 7, 9]])
B = np.array([[0, 1, 5], [4, 7, 9]])
B
## array([[0, 1, 5],
##        [4, 7, 9]])
C = np.array([[0, 1, 5], [4, 7, 9], [6, 2, 7]])
C
## array([[0, 1, 5],
##        [4, 7, 9],
##        [6, 2, 7]])

## Matrix Indexing

We use the matrix notation $$M_{ij}$$ where $$M$$ is a matrix.

A[0][2] 
## 5

## Square, Tall, and Wide Matrices

A square matrix has an equal number of rows and columns. A square matrix of size $$n \times n$$ is said to be of order $$n$$. A tall matrix has more rows than columns. A wide matrix has more columns than rows.

## Column and Row Vectors

An $$n$$-vector can be interpreted as an $$n \times 1$$ matrix, also called a column vector. A matrix with only one row, meaning with size $$1 \times n$$ is called a row vector. A $$1 \times 1$$ matrix is considered to be the same as a scalar.

## Columns and Rows of a Matrix

An $$m \times n$$ matrix $$A$$ has $$n$$ columns, given the the $$m$$-vectors

$a_j = \begin{bmatrix} A_{1j} \\ \vdots \\ A_{mj} \end{bmatrix}$

for $$j = 1, \cdots, n$$. The same matrix as $$m$$ rows, given by the $$n$$-row vectors

$b_i = [ \ A_{i1} \ \cdots \ A_{in} \ ]$

## Block Matrices and Submatrices

It is useful to consider matrices whose entries are themselves matrices.

$A = \begin{bmatrix} B & C \\ D & E \end{bmatrix}$

where $$B$$, $$C$$, $$D$$, $$E$$ are matrices. Such matrices are called block matrices. The elements are called blocks or submatrices. They can be referred to by their block row and column.

Block matrices must have the right dimensions to fit together. Metrics in the same (block) row must have the same number of rows (or height); matrices int he same (block) column must have the same number of columns (or width). So, $$B$$ and $$C$$ must have the same number of rows, and $$C$$ and $$E$$ must have the same number of columns.

Matrix blocks placed next to each other in the same row are said to be concatenated; matrix blocks placed above each other are called stacked.

P11 = np.vstack([[1, 2], [1, 5]])
P12 = np.vstack([[2, 7], [6, 2]])
P21 = np.vstack([[3, 3], [3, 3]])
P22 = np.vstack([[4, 5], [6, 7]])

P = np.block([[P11, P12], [P21, P22]])
P
## array([[1, 2, 2, 7],
##        [1, 5, 6, 2],
##        [3, 3, 4, 5],
##        [3, 3, 6, 7]])