[譯] JavaScript 線性代數:線性變換與矩陣

JavaScript 線性代數:線性變換與矩陣

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

矩陣是一種由 mn 列實數組成的「矩形」數組。好比,一個 3x2 的矩陣以下所示:前端

**3×2** 矩陣

Matrix 類的構造器(constructor)接收若干行元素做爲參數。咱們能夠經過指定行號取出矩陣中的一行,而後再經過指定列號取出一個特定的元素。下面直接看代碼:java

class Matrix {
  constructor(...rows) {
    this.rows = rows
  }
}

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

矩陣與向量的乘積

矩陣與向量的乘法 —— A\vec{x} 會將矩陣 A 的列進行係數爲 \vec{x} 的線性組合。好比,一個 3\times 2 的矩陣 A 與一個 2D 向量 \vec{x} 的乘積將獲得一個 3D 向量,這個計算記爲:\vec{y} : \vec{y} = A\vec{x}android

**y⃗=Ax⃗**

假設有一組向量 \{\vec{e}_1,\vec{e}_2\},另外一個向量 \vec{y}\vec{e}_1\vec{e}_2線性組合\vec{y} = \alpha\vec{e}_1 + \beta \vec{e}_2。其中,\alpha, \beta \in \mathbb{R} 就是這個線性組合的係數。ios

爲了更好地學習線性組合,咱們特意爲此定義了矩陣向量乘法。咱們能夠將前面所說的線性組合記爲如下矩陣向量乘法的形式:\vec{y} = E \vec{x}。矩陣 E\vec{e}_1\vec{e}_2 兩列。矩陣的維數是 n \times 2,其中 n 是向量 \vec{e}_1\vec{e}_2\vec{y} 的維數。git

下圖展現了將向量 \vec{v} 表示爲向量 \vec{\imath} 和向量 \vec{\jmath} 的線性組合:github

線性組合

const i = new Vector(1, 0)
const j = new Vector(0, 1)
const firstCoeff = 2
const secondCoeff = 5
const linearCombination = i.scaleBy(firstCoeff).add(j.scaleBy(secondCoeff))
console.log(linearCombination)
// Vector { components: [ 2, 5 ] }
複製代碼

線性變換

矩陣與向量的乘法是線性變換的抽象概念,這是學習線性代數中的關鍵概念之一。向量與矩陣的乘法能夠視爲對向量進行線性變換:將 n 維向量做爲輸入,並輸出 m 維向量。也能夠說,矩陣是定義好的某種空間變換。後端

咱們能夠經過一個示例來更清楚地理解線性變換。首先須要給 Matrix 類加上一個方法,用於返回矩陣的列:數組

class Matrix {
  constructor(...rows) {
    this.rows = rows
  }
  columns() {
    return this.rows[0].map((_, i) => this.rows.map(r => r[i]))
  }
}

const matrix = new Matrix(
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9]
)
console.log(matrix.columns())
// [ [ 1, 4, 7 ], [ 2, 5, 8 ], [ 3, 6, 9 ] ]
複製代碼

乘法獲得的向量的維數將與矩陣的行數相同。若是咱們將一個 2D 向量和一個 3x2 矩陣相乘,將獲得一個 3D 的向量;若是將一個 3D 向量和一個 2x3 矩陣相乘,將獲得一個 2D 的向量;若是在作乘法時,矩陣的列數和向量的維數不相同,將報錯。在下面的代碼中,你能夠看到幾種不一樣的向量與矩陣相乘的形式:學習

const sum = arr => arr.reduce((acc, value) => acc + value, 0)

class Vector {
  // ...
  transform(matrix) {
    const columns = matrix.columns()
    if(columns.length !== this.components.length) {
      throw new Error('Matrix columns length should be equal to vector components length.')
    }

    const multiplied = columns
      .map((column, i) => column.map(c => c * this.components[i]))
    const newComponents = multiplied[0].map((_, i) => sum(multiplied.map(column => column[i])))
    return new Vector(...newComponents)
  }
}

const vector2D = new Vector(3, 5)
const vector3D = new Vector(3, 5, 2)
const matrix2x2D = new Matrix(
  [1, 2],
  [3, 4]
)
const matrix2x3D = new Matrix(
  [1, 2, 3],
  [4, 5, 6]
)
const matrix3x2D = new Matrix(
  [1, 2],
  [3, 4],
  [5, 6]
)

// 2D => 2D
console.log(vector2D.transform(matrix2x2D))
// Vector { components: [ 13, 29 ] }

// 3D => 2D
console.log(vector3D.transform(matrix2x3D))
// Vector { components: [ 19, 49 ] }

// 2D => 3D
console.log(vector2D.transform(matrix3x2D))
// Vector { components: [ 13, 29, 45 ] }
console.log(vector2D.transform(matrix2x3D))
// Error: Matrix columns length should be equal to vector components length.
複製代碼

示例

如今,咱們將嘗試對二維的對象應用線性變換。首先,須要建立一個新的 Contour(輪廓)類,它在 constructor 中接收一系列的向量(在 2D 平面中造成一個輪廓),而後用惟一的方法 —— transform 對輪廓中的全部向量座標進行變換,最後返回一個新的輪廓。

class Contour {
  constructor(vectors) {
    this.vectors = vectors
  }

  transform(matrix) {
    const newVectors = this.vectors.map(v => v.transform(matrix))
    return new Contour(newVectors)
  }
}

const contour = new Contour([
  new Vector(0, 0),
  new Vector(0, 4),
  new Vector(4, 4),
  new Vector(4, 0)
])
複製代碼

如今,請在 linear-algebra-demo 項目中試試各類轉換矩陣。紅色方塊是初始化的輪廓,藍色形狀是應用變換矩陣後的輪廓。

鏡像

縮放

經過下面的方式,咱們能夠構建一個矩陣,用於將給定的向量旋轉指定的角度。

const angle = toRadians(45)

const matrix = new Matrix(
  [Math.cos(angle), -Math.sin(angle)],
  [Math.sin(angle), Math.cos(angle)]
)
複製代碼

旋轉

剪切變換

對 3D 空間內的對象進行變換也與此相似。你能夠在下圖中看到一個紅色方塊變換成一個藍色的平行六邊形的動畫。

3D 剪切變換

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


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

相關文章
相關標籤/搜索