JavaScript
 Computer >> コンピューター >  >> プログラミング >> JavaScript

JavaScriptで実装する行列乗算アルゴリズムの完全ガイド

はじめに

本記事では、2つの2次元数値配列(行列)を受け取り、その行列乗算の結果を返すJavaScript関数を実装していきます。

行列乗算の基本ルール

行列AがX行Z列、行列BがZ行Y列である場合、乗算結果はX行Y列の行列になります。したがって、最初の行列の列数と2番目の行列の行数は必ず一致している必要があり、一致しない場合は計算できません。

実装コード

以下が実際のコードです。

const multiplyMatrices = (a, b) => {
    if (!Array.isArray(a) || !Array.isArray(b) || !a.length || !b.length) {
        throw new Error('引数は2次元配列形式である必要があります');
    }
    let x = a.length,
    z = a[0].length,
    y = b[0].length;
    if (b.length !== z) {
        // XxZ & ZxY => XxY
        throw new Error('1つ目の行列の列数は、
        2つ目の行列の行数と同じである必要があります');
    }
    let productRow = Array.apply(null, new Array(y)).map(Number.prototype.valueOf, 0);
    let product = new Array(x);
    for (let p = 0; p < x; p++) {
        product[p] = productRow.slice();
    }
    for (let i = 0; i < x; i++) {
        for (let j = 0; j < y; j++) {
            for (let k = 0; k < z; k++) {
                product[i][j] += a[i][k] * b[k][j];
            }
        }
    }
    return product;
}
// 5 x 4 の行列
let a = [
    [1, 2, 3, 1],
    [4, 5, 6, 1],
    [7, 8, 9, 1],
    [1, 1, 1, 1],
    [5, 7, 2, 6]
];
// 4 x 6 の行列
let b = [
    [1, 4, 7, 3, 4, 6],
    [2, 5, 8, 7, 3, 2],
    [3, 6, 9, 6, 7, 8],
    [1, 1, 1, 2, 3, 6]
];
// 結果は 5 x 6 の行列になる
console.log(multiplyMatrices(a, b));

出力結果

コンソールには次のように表示されます。

[
    [ 15, 33, 51, 37, 34, 40 ],
    [ 33, 78, 123, 85, 76, 88 ],
    [ 51, 123, 195, 133, 118, 136 ],
    [ 7, 16, 25, 18, 17, 22 ],
    [ 31, 73, 115, 88, 73, 96 ]
]

コードの解説

この関数の処理の流れは以下の通りです。

1. 入力値の検証:まず、両方の引数が空でない配列かどうかをチェックし、不正な場合はエラーを投げます。

2. 行列サイズの整合性チェック:1つ目の行列の列数(z)と2つ目の行列の行数が一致していることを確認します。これにより、「XxZ × ZxY = XxY」という行列乗算のルールが満たされます。

3. 結果行列の初期化:すべての要素を0で埋めたX行Y列の2次元配列を作成し、結果の格納先として準備します。

4. 三重ループによる計算:i・j・kの3つのインデックスを使ったネストされたループの中で、「product[i][j] += a[i][k] * b[k][j]」という式により内積を累積していくのが核心部分です。

なお、この素朴な実装の計算量はO(X×Y×Z)であり、大規模な行列を扱う場合はStrassen法などの高速化アルゴリズムや、専用の数値計算ライブラリの利用も検討するとよいでしょう。

  1. JavaScriptのconstとletの違いを徹底解説!ブロックスコープ変数の基本と使い方

    JavaScriptにおけるconstとletの基本const と let は、ES2015(ES6)で導入された変数宣言用のキーワードです。どちらもブロックスコープ(波括弧 { } で囲まれた範囲)に対応しているのが特徴で、関数スコープしか持たなかった従来の var とは異なる挙動を示します。両者の大きな違いは再代入の可否です。letで宣言した変数は後から何度でも値を再代入できますが、constで宣言した変数は再代入しようとするとエラー(TypeError)が発生します。letとconstの主な違い項目letconst再代入可能不可(エラー発生)スコープブロックスコープブロックスコープ宣言時

  2. JavaScriptの「for...in」ステートメントとは?オブジェクトのプロパティをループ処理する方法を解説

    JavaScriptのfor...in文は、オブジェクトが持つすべてのプロパティ(列挙可能なプロパティ)を順番に取り出して処理するためのループ構文です。オブジェクト内の各キー(プロパティ名)にアクセスしながら、対応する値を取得したい場合に非常に便利です。for...inの基本的な構文for (let 変数名 in オブジェクト) { // 各プロパティに対して実行したい処理 }ループ変数には、各反復ごとにオブジェクトのプロパティ名(キー)が文字列として代入されます。値そのものを取得するには、「オブジェクト[変数名]」のようにブラケット記法を使ってアクセスします。サンプルコード以下は、for