[譯] 線性代數:矩陣基本運算

線性代數:矩陣基本運算

本文是「JavaScript 線性代數」教程的一部分。javascript

在本文中,咱們將介紹矩陣的大部分基本運算,依次是矩陣的加減法、矩陣的標量乘法、矩陣與矩陣的乘法、求轉置矩陣,以及深刻了解矩陣的行列式運算。本文將不會涉及逆矩陣、矩陣的秩等概念,未來再探討它們。前端

矩陣的加減法

矩陣的加法減法運算將接收兩個矩陣做爲輸入,並輸出一個新的矩陣。矩陣的加法和減法都是在份量級別上進行的,所以要進行加減的矩陣必須有着相同的維數。java

爲了不重複編寫加減法的代碼,咱們先建立一個能夠接收運算函數的方法,這個方法將對兩個矩陣的份量分別執行傳入的某種運算。而後在加法、減法或者其它運算中直接調用它就好了:android

class Matrix {
  // ...
  componentWiseOperation(func, { rows }) {
    const newRows = rows.map((row, i) =>
      row.map((element, j) => func(this.rows[i][j], element))
    )
    return new Matrix(...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 ] ] }
複製代碼

矩陣的標量乘法

矩陣的標量乘法與向量的縮放相似,就是將矩陣中的每一個元素都乘上標量:ios

class Matrix {
  // ...
  scaleBy(number) {
    const newRows = this.rows.map(row =>
      row.map(element => element * number)
    )
    return new Matrix(...newRows)
  }
}

const matrix = new Matrix(
  [2, 3],
  [4, 5]
)
console.log(matrix.scaleBy(2))
// Matrix { rows: [ [ 4, 6 ], [ 8, 10 ] ] }
複製代碼

矩陣乘法

AB 兩個矩陣的維數是兼容的時候,就能對這兩個矩陣進行矩陣乘法。所謂維數兼容,指的是 A 的列數與 B 的行數相同。矩陣的乘積 AB 是經過對 A 的每一行與矩陣 B 的每一列計算點積獲得:git

矩陣乘法圖解

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 new Matrix(...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 ] ]}
複製代碼

咱們能夠把矩陣乘法 AB 視爲前後應用 AB 兩個線性變換矩陣。爲了更好地理解這種概念,能夠看一看咱們的 linear-algebra-demogithub

下圖中黃色的部分就是對紅色方塊應用線性變換 C 的結果。而線性變換 C 就是矩陣乘法 AB 的結果,其中 A 是作相對於 y 軸進行反射的變換矩陣,B 是作剪切變換的矩陣。後端

先旋轉再剪切變換

若是在矩陣乘法中調換 AB 的順序,咱們會獲得一個不一樣的結果,由於至關於先應用了 B 的剪切變換,再應用 A 的反射變換:函數

先剪切變換再旋轉

轉置

轉置矩陣 A^T 由公式 a^T_{ij}=a_{ji} 定義。換句話說,咱們經過關於矩陣的對角線對其進行翻轉來獲得轉置矩陣。須要注意的是,矩陣對角線上的元素不受轉置運算影響。區塊鏈

class Matrix {
  // ...
  transpose() {
    return new Matrix(...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 ]
// ]
// }
複製代碼

行列式運算

矩陣的行列式運算將計算矩陣中的全部係數,最後輸出一個數字。準確地說,行列式能夠描述一個由矩陣行構成的向量的相對幾何指標(好比在歐式空間中的有向面積、體積等空間概念)。更準確地說,矩陣 A 的行列式至關於告訴你由 A 的行定義的方塊的體積。2\times 2 矩陣的行列式運算以下所示:

det(2×2 matrix)

3\times 3 矩陣的行列式運算以下所示:

det(3×3 matrix)

咱們的方法能夠計算任意大小矩陣(只要其行列的數量相同)的行列式:

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 = new Matrix(...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
複製代碼

行列式能夠告訴咱們變換時對象被拉伸的程度。所以咱們能夠將其視爲線性變換改變面積的因子。爲了更好地理解這個概念,請參考 linear-algebra-demo

在下圖中,咱們能夠看到對紅色的 1×1 方形進行線性變換後獲得了一個 3×2 的長方形,面積從 1 變爲了 6,這個數字與線性變換矩陣的行列式值相同。

det(scale transformation)

若是咱們應用一個剪切變換,能夠看到方形會變成一個面積不變的平行四邊形。所以,剪切變換矩陣的行列式值等於 1:

det(shear transformation)

若是行列式的值是負數,則說明應用線性變換後,空間被反轉了。好比在下圖中,咱們能夠看到變換前 \hat{\jmath}\hat{\imath} 的左邊,而變換後 \hat{\jmath}\hat{\imath} 的右邊。

negative determinant

若是變換的行列式爲 0,則表示它會將全部空間都壓縮到一條線或一個點上。也就是說,計算一個給定矩陣的行列式是否爲 0,能夠判斷這個矩陣對應的線性變換是否會將對象壓縮到更小的維度去。

2D 中的 0 行列式

在三維空間裏,行列式能夠告訴你體積縮放了多少:

det(scale transformation) in 3D

變換行列式等於 0,意味着原來的空間會被徹底壓縮成體積爲 0 的空間。如前文所說,若是在 2 維空間中變換的行列式爲 0,則意味着變換的結果將空間壓縮成了一條線或一個點;而在 3 維空間中變換的行列式爲 0 意味着一個物體會被壓扁成一個平面,以下圖所示:

3D 中的 0 行列式

若是發現譯文存在錯誤或其餘須要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可得到相應獎勵積分。文章開頭的 本文永久連接 即爲本文在 GitHub 上的 MarkDown 連接。


掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章
相關標籤/搜索