• Linear Algebra: Basic Matrix Operations
  • Rodion Chachura
  • The Nuggets translation Project
  • Permanent link to this article: github.com/xitu/gold-m…
  • Translator: lsvih
  • Proofreader: JackEggie, Shixi-Li

Linear algebra: Basic operations on matrices

This article is part of the “JavaScript Linear Algebra” tutorial.

In this article, we will introduce most of the basic operations of matrices, which are addition and subtraction of matrices, scalar multiplication of matrices, multiplication of matrices with matrices, finding transpose matrices, and further understanding of determinant operations of matrices. Concepts such as inverse matrices and the rank of matrices will not be covered in this paper, but will be discussed in the future.

Matrix addition and subtraction

Matrix addition and subtraction takes two matrices as inputs and outputs a new matrix. Matrix addition and subtraction are done at the component level, so the matrices to be added and subtracted must have the same dimension.

To avoid repeating the code of addition and subtraction, we first create a method that accepts an operation function that performs some of the incoming operations on the components of the two matrices. Then call it directly in addition, subtraction, or other operations:

class Matrix {
  // ...
  componentWiseOperation(func, { rows }) {
    const newRows = rows.map((row, i) = >
      row.map((element, j) = > func(this.rows[i][j], element))
    )
    return newMatrix(... newRows) } add(other) {return this.componentWiseOperation((a, b) = > a + b, other)
  }
  subtract(other) {
    return this.componentWiseOperation((a, b) = > a - b, other)
  }
}

const one = new Matrix(
  [1.2],
  [3.4])const other = new Matrix(
  [5.6],
  [7.8])console.log(one.add(other))
// Matrix { rows: [ [ 6, 8 ], [ 10, 12 ] ] }
console.log(other.subtract(one))
// Matrix { rows: [ [ 4, 4 ], [ 4, 4 ] ] }
Copy the code

Scalar multiplication of matrices

Scalar multiplication of a matrix is similar to scaling of vectors by multiplying each element in the matrix by a scalar:

class Matrix {
  // ...
  scaleBy(number) {
    const newRows = this.rows.map(row= >
      row.map(element= > element * number)
    )
    return newMatrix(... newRows) } }const matrix = new Matrix(
  [2.3],
  [4.5])console.log(matrix.scaleBy(2))
// Matrix { rows: [ [ 4, 6 ], [ 8, 10 ] ] }
Copy the code

Matrix multiplication

When the dimensions of matrices A and B are compatible, matrix multiplication can be performed on the two matrices. Dimensional compatibility means that A has the same number of columns as B. The matrix product AB is obtained by taking the dot product of each row of A with each column of matrix B:

class Matrix {
  // ...
  multiply(other) {
    if (this.rows[0].length ! == other.rows.length) {throw new Error('The number of columns of this matrix is not equal to the number of rows of the given matrix.')}const columns = other.columns()
    const newRows = this.rows.map(row= > 
      columns.map(column= > sum(row.map((element, i) = > element * column[i])))
    )

    return newMatrix(... newRows) } }const one = new Matrix(
  [3.4 -],
  [0.- 3],
  [6.2 -],
  [- 1.1])const other = new Matrix(
  [3.2.4 -],
  [4.- 3.5])console.log(one.multiply(other))
// Matrix {
// rows:
// [[-7, 18, -32],
// [-12, 9, -15],
// [10, 18, -34],
// [1, -5, 9]]}
Copy the code

We can think of matrix multiplication AB as applying two linear transformation matrices A and B successively. To better understand this concept, take a look at our Linear-Opencoursed-demo.

The yellow part in the figure below is the result of applying the linear transformation C to the red square. The linear transformation C is the result of matrix multiplication AB, where A is the transformation matrix for reflection with respect to the Y-axis and B is the matrix for shear transformation.

If we reverse the order of A and B in the matrix multiplication, we will get A different result, because it is equivalent to applying the shear transformation of B first and then applying the reflection transformation of A:

transpose

transposematrixBy the formulaDefinition. In other words, we take the diagonal of the matrix and flip it to get the transpose. Note that the elements on the diagonal of the matrix are not affected by transpose.

class Matrix {
  // ...
  transpose() {
    return newMatrix(... this.columns()) } }const matrix = new Matrix(
  [0.1.2],
  [3.4.5],
  [6.7.8],
  [9.10.11])console.log(matrix.transpose())
// Matrix {
// rows: [
// [0, 3, 6, 9],
// [1, 4, 7, 10],
// [2, 5, 8, 11]
/ /]
// }
Copy the code

Determinant operation

matrixThe determinantThe operation computes all the coefficients in the matrix and outputs a number. To be precise, a determinant can describe the relative geometric indices of a vector made up of rows of a matrix (such as the spatial concepts of directed area and volume in Euclidean space). More precisely, matricesAThe determinant of phi is the same thing as telling you the determinant of phiAThe row defines the volume of the square.The determinant operation of the matrix is as follows:

The determinant operation of the matrix is as follows:

Our method computes the determinant of any size matrix (as long as it has the same number of rows and columns) :

class Matrix {
  // ...
  determinant() {
    if (this.rows.length ! = =this.rows[0].length) {
      throw new Error('Only matrices with the same number of rows and columns are supported.')}if (this.rows.length === 2) {
      return this.rows[0] [0] * this.rows[1] [1] - this.rows[0] [1] * this.rows[1] [0]}const parts = this.rows[0].map((coef, index) = > {
      const matrixRows = this.rows.slice(1).map(row= > [ ...row.slice(0, index), ... row.slice(index +1)])
      const matrix = newMatrix(... matrixRows)const result = coef * matrix.determinant()
      return index % 2= = =0 ? result : -result
    })

    return sum(parts)
  }
}

const matrix2 = new Matrix(
  [ 0.3],
  [2 -.1])console.log(matrix2.determinant())
/ / 6
const matrix3 = new Matrix(
  [2.- 3.1],
  [2.0.- 1],
  [1.4.5])console.log(matrix3.determinant())
/ / 49
const matrix4 = new Matrix(
  [3.0.2.- 1],
  [1.2.0.2 -],
  [4.0.6.- 3],
  [5.0.2.0])console.log(matrix4.determinant())
/ / 20
Copy the code

The determinant tells us how much the object is stretched when we transform it. So we can view it as a factor of a linear transformation that changes the area. To better understand this concept, refer to Linear-opencoursed-demo:

In the figure below, we can see that the linear transformation of the red 1×1 square results in a 3×2 rectangle with area changed from 1 to 6. This number is the same as the determinant of the linear transformation matrix.

If we apply a shear transformation, we can see that the square will become a parallelogram with constant area. Therefore, the determinant of the shear transformation matrix is equal to 1:

If the determinant is zeroA negative number, it means that after applying linear transformation, the space is reversed. For example, in the figure below, we can see before the transformationTo the left of theta, and the transformationOn the right.

If the determinant of the transformation is 0, it means that it compresses all space to a line or point. In other words, calculating whether the determinant of a given matrix is zero can determine whether the linear transformation of the matrix will compress the object into smaller dimensions.

In three dimensions, the determinant tells you how much the volume is scaled:

The determinant of the transformation is equal to 0, which means that the original space is completely compressed to 0. As mentioned above, if the determinant of a transformation in 2-dimensional space is 0, it means that the result of the transformation reduces the space to a line or a point; The determinant of a transformation of 0 in three dimensions means that an object is squashed into a plane, as shown below:

If you find any mistakes in your translation or other areas that need to be improved, you are welcome to the Nuggets Translation Program to revise and PR your translation, and you can also get the corresponding reward points. The permanent link to this article at the beginning of this article is the MarkDown link to this article on GitHub.


The Nuggets Translation Project is a community that translates quality Internet technical articles from English sharing articles on nuggets. The content covers Android, iOS, front-end, back-end, blockchain, products, design, artificial intelligence and other fields. If you want to see more high-quality translation, please continue to pay attention to the Translation plan of Digging Gold, the official Weibo, Zhihu column.