JavaScript の数学ライブラリ Math.js を使って行列の計算をしてみました。
Math.js の行列のサンプルコードをベースに主な機能を使ってみました。
<script src="https://unpkg.com/mathjs@9.5.0/lib/browser/math.js">
HTML の <body> タグに以下のコードを埋め込みました。
このコードは Math.js のサンプルコードをベースにしています。
/** * 結果表示用の関数です。HTMLとして展開します。 * @since 0.1 */ function writeln(str) { document.writeln(str + "<br>"); } function write(str) { document.writeln(str); } /** * コメントを表示する関数です。 * @sinse 0.1 */ function comment(str) { writeln("<span style='color: lime'>// " + str + "</span>"); } /** * テストの実行と表示を行う関数です。 * @since 0.1 */ function test(exp) { write(exp + " "); var ans = eval(exp); comment(ans); } comment("行列と配列を作成します。 行列は Array の単なるラッパーであり、") comment("いくつかの便利なユーティリティを提供します。") test("a = math.matrix([1, 4, 9, 16, 25])") // [1, 4, 9, 16, 25] test("a.size()") // 5 test("precision = 4") // 4 test("math.format(a.size(), precision)") // [5] test("b = math.matrix(math.ones([2, 3]))") // [[1, 1, 1], [1, 1, 1]] test("b.size()") // 2,3 test("math.format(b.size(), precision)") // [2, 3] writeln("") comment("行列の配列データは、valueOf() を使用して取得できます。") test("a") // [1, 4, 9, 16, 25] test("array = a.valueOf()") // 1,4,9,16,25 test("b") // [[1, 1, 1], [1, 1, 1]] test("b.valueOf()") // 1,1,1,1,1,1 test("math.format(b.valueOf(), precision)") // [[1, 1, 1], [1, 1, 1]] writeln("") comment("行列はコピーできます。") test("clone = a.clone()") // [1, 4, 9, 16, 25] test("clone") // [1, 4, 9, 16, 25] writeln("") comment("行列の演算") test("math.sqrt(a)") // [1, 2, 3, 4, 5] test("c = [1, 2, 3, 4, 5]") // 1,2,3,4,5 test("math.factorial(c)") // [1, 2, 6, 24, 120] writeln("") comment("行列の作成および操作。 配列と行列は混合して使用できます。") test("d = [[1, 2], [3, 4]]") // 1,2,3,4 test("math.format(d, precision)") // [[1, 2], [3, 4]] test("e = math.matrix([[5, 6], [1, 1]])") // [[5, 6], [1, 1]] writeln("") comment("部分行列の設定") comment("行列のインデックスはゼロベースです。") test("e.subset(math.index(1, [0, 1]), [[7, 8]])") // [[5, 6], [7, 8]] test("f = math.multiply(d, e)") // [[19, 22], [43, 50]] test("math.add(d, e)") // [[6, 8], [10, 12]] test("g = f.subset(math.index(1, 0))") // 43 writeln("") comment("部分行列の取得") comment("行列のインデックスはゼロベースです。") test("h = math.diag(math.range(1, 4))") // [[1, 0, 0], [0, 2, 0], [0, 0, 3]] test("h.subset(math.index([1, 2], [1, 2]))") // [[2, 0], [0, 3]] test("i = math.range(1, 6)") // [1, 2, 3, 4, 5] test("i.subset(math.index(math.range(1, 4)))") // [2, 3, 4] writeln("") comment("多次元行列のリサイズ") test("j = math.matrix()") test("defaultValue = 0") test("j.resize([2, 2, 2], defaultValue)") // [[[0, 0], [0, 0]], [[0, 0], [0, 0]]] test("j.size()") // 2, 2, 2 test("j.resize([2, 2])") // [[0, 0], [0, 0]] test("j.size()") // 2,2 writeln("") comment("行列の範囲外の値を設定すると、行列のサイズが変更されます。") comment("新しい要素はゼロで初期化されます。") test("k = math.matrix()") test("k.subset(math.index(2), 6)") // [0, 0, 6] writeln("") comment("新しい要素を null に設定しながら、行列の範囲外の値を設定") test("m = math.matrix()") test("defaultValue = null") test("m.subset(math.index(2), 6, defaultValue)") // [null, null, 6] writeln("") comment("範囲の作成") test("math.range(1, 6)") // [1, 2, 3, 4, 5] test("math.range(0, 18, 3)") // [0, 3, 6, 9, 12, 15] test("math.range('2:-1:-3')") // [2, 1, 0, -1, -2] test("math.factorial(math.range('1:6'))") // [1, 2, 6, 24, 120] writeln("")
Math.js でベクトルの定義と計算を行ってみました。
<script src="https://unpkg.com/mathjs@9.5.0/lib/browser/math.js">
HTML の <body> タグに以下のコードを埋め込みました。
/** * 結果表示用の関数です。HTMLとして展開します。 * @since 0.1 */ function writeln(str) { document.writeln(str + "<br>"); } function write(str) { document.writeln(str); } /** * コメントを表示する関数です。 * @sinse 0.1 */ function comment(str) { writeln("<span style='color: lime'>// " + str + "</span>"); } /** * テストの実行と表示を行う関数です。 * @since 0.1 */ function test(exp) { write(exp + " "); var ans = eval(exp); comment(ans); } comment("配列による行ベクトルの定義") test("r1 = math.matrix([[1, 0, 0]])") // [[1, 0, 0]] test("r1.size()") // 1,3 test("precision = 4") // 4 test("math.format(r1.size(), precision)") // [1, 3] writeln("") comment("転置 transpose による列ベクトルの定義") test("c1 = math.transpose(r1)") // [[1], [0], [0]] test("c1.size()") // 3,1 test("math.format(c1.size(), precision)") // [3, 1] writeln("") comment("zeros による行ベクトルの定義") test("r0 = math.matrix(math.zeros(1, 3))") // [[0, 0, 0]] comment("subset による行ベクトルの定義") test("r2 = r0.subset(math.index(0, 1), 1)") // [[0, 1, 0]] comment("行ベクトルの和") test("r12 = math.add(r1, r2)") // [[1, 1, 0]] writeln("") comment("zeros による列ベクトルの定義") test("c0 = math.matrix(math.zeros(3, 1))") // [[0], [0], [0]] comment("subset による列ベクトルの定義") test("c2 = c0.subset(math.index(1, 0), 1)") // [[0], [1], [0]] writeln("") comment("行ベクトルを配列として取り出す") test("array = r1.valueOf()") // 1,0,0 comment("format による表示") test("math.format(array, precision)") // [[1, 0, 0]] comment("行ベクトルの要素") test("array[0][0]") // 1 test("array[0][1]") // 0 test("array[0][2]") // 0 writeln("") comment("列ベクトルを配列として取り出す") test("array = c2.valueOf()") // 0,1,0 comment("format による表示") test("math.format(array, precision)") // [[0], [1], [0]] comment("列ベクトルの要素") test("array[0][0]") // 0 test("array[1][0]") // 1 test("array[2][0]") // 0 writeln("") comment("ベクトルの演算") test("v1 = math.matrix([[1, 2, 3]])") // [[1, 2, 3]] test("v2 = math.matrix([[4, 5, 6]])") // [[4, 5, 6]] comment("和") test("math.add(v1, v2)") // [[5, 7, 9]] comment("差") test("math.subtract(v1, v2)") // [[-3, -3, -3]] comment("内積") test("math.multiply(v1, math.transpose(v2))") // [[32]] comment("外積") test("math.multiply(math.transpose(v1), v2)") // [[4, 5, 6], [8, 10, 12], [12, 15, 18]] writeln("")
Math.js で計算した行列を TEX に変換してみました。
<script src="https://unpkg.com/mathjs@9.5.0/lib/browser/math.js">
HTML の <body> タグに以下のコードを埋め込みました。
/** * 結果表示用の関数です。HTMLとして展開します。 * @since 0.1 */ function writeln(str) { document.writeln(str + "<br>"); } function write(str) { document.writeln(str); } /** * コメントを表示する関数です。 * @sinse 0.1 */ function comment(str) { writeln("<span style='color: lime'>// " + str + "</span>"); } /** * 複数行のコメントを表示する関数です。 * @sinse 0.3 */ function comment1(str) { writeln("<div style='color: lime'>/* " + str) } function comment2(str) { writeln(str) } function comment3(str) { writeln(str + " */</div>") } /** * 行列をTeXに変換する関数です。 * @sinse 0.3 */ function matrix2tex(mtx) { typ = math.typeOf(mtx) if (typ == "Matrix" || typ == "Array") { dim = mtx.size() rows = dim[0] cols = dim[1] tex = "\\begin{bmatrix}<br>" for (i = 0; i < rows; i++) { for (j = 0; j < cols; j++) { tex += mtx.subset(math.index(i, j)) if (j < cols - 1) { tex += " \& " } } if (i < rows - 1) { tex += " \\\\" } tex += "<br>" } tex += "\\end{bmatrix}" } else { tex = mtx } return tex } /** * テストの実行と表示を行う関数です。 * @since 0.1 */ function test(exp) { write(exp + " "); var ans = eval(exp); comment(ans); } /** * 行列の結果をテキストとTeXで行う関数です。 * @since 0.3 */ function testM(exp) { write(exp + " ") var ans = eval(exp) comment(ans) var tex = matrix2tex(ans) comment1("TeX") comment2(tex) comment3("") } comment("交点ベクトル v[i] の定義") v = [] v[0] = math.matrix(math.zeros(1, 9)) for (i = 1; i <= 9; i++) { v[i] = v[0].clone() v[i].subset(math.index(0, i - 1), 1) } testM("v[0]") // [[0, 0, 0, 0, 0, 0, 0, 0, 0]] testM("v[1]") // [[1, 0, 0, 0, 0, 0, 0, 0, 0]] testM("v[9]") // [[0, 0, 0, 0, 0, 0, 0, 0, 1]] writeln("") comment("隣接行列 A[1] の定義") A = [] A[1] = math.matrix() testM("math.add(v[2],v[4])") A[1].subset(math.index(0, math.range(0, 9)), math.add(v[2], v[4])) A[1].subset(math.index(1, math.range(0, 9)), math.add(math.add(v[1], v[3]), v[5])) A[1].subset(math.index(2, math.range(0, 9)), math.add(v[2], v[6])) A[1].subset(math.index(3, math.range(0, 9)), math.add(math.add(v[1], v[5]), v[7])) A[1].subset(math.index(4, math.range(0, 9)), math.add(math.add(math.add(v[2], v[4]), v[6]), v[8])) A[1].subset(math.index(5, math.range(0, 9)), math.add(math.add(v[3], v[5]), v[9])) A[1].subset(math.index(6, math.range(0, 9)), math.add(v[4], v[8])) A[1].subset(math.index(7, math.range(0, 9)), math.add(math.add(v[5], v[7]), v[9])) A[1].subset(math.index(8, math.range(0, 9)), math.add(v[6], v[8])) testM("A[1]") // [[0, 1, 0, 1, 0, 0, 0, 0, 0], [1, 0, 1, 0, 1, 0, 0, 0, 0], [0, 1, 0, 0, 0, 1, 0, 0, 0], [1, 0, 0, 0, 1, 0, 1, 0, 0], [0, 1, 0, 1, 0, 1, 0, 1, 0], [0, 0, 1, 0, 1, 0, 0, 0, 1], [0, 0, 0, 1, 0, 0, 0, 1, 0], [0, 0, 0, 0, 1, 0, 1, 0, 1], [0, 0, 0, 0, 0, 1, 0, 1, 0]] writeln("") comment("隣接行列 A[1] の2乗 A[1]^2") testM("A[2] = math.multiply(A[1], A[1])") // [[2, 0, 1, 0, 2, 0, 1, 0, 0], [0, 3, 0, 2, 0, 2, 0, 1, 0], [1, 0, 2, 0, 2, 0, 0, 0, 1], [0, 2, 0, 3, 0, 1, 0, 2, 0], [2, 0, 2, 0, 4, 0, 2, 0, 2], [0, 2, 0, 1, 0, 3, 0, 2, 0], [1, 0, 0, 0, 2, 0, 2, 0, 1], [0, 1, 0, 2, 0, 2, 0, 3, 0], [0, 0, 1, 0, 2, 0, 1, 0, 2]] comment("隣接行列 A[1] の3乗 A[1]^3") testM("A[3] = math.multiply(A[2], A[1])") // [[0, 5, 0, 5, 0, 3, 0, 3, 0], [5, 0, 5, 0, 8, 0, 3, 0, 3], [0, 5, 0, 3, 0, 5, 0, 3, 0], [5, 0, 3, 0, 8, 0, 5, 0, 3], [0, 8, 0, 8, 0, 8, 0, 8, 0], [3, 0, 5, 0, 8, 0, 3, 0, 5], [0, 3, 0, 5, 0, 3, 0, 5, 0], [3, 0, 3, 0, 8, 0, 5, 0, 5], [0, 3, 0, 3, 0, 5, 0, 5, 0]] comment("隣接行列 A[1] の4乗 A[1]^4") testM("A[4] = math.multiply(A[3], A[1])") // [[10, 0, 8, 0, 16, 0, 8, 0, 6], [0, 18, 0, 16, 0, 16, 0, 14, 0], [8, 0, 10, 0, 16, 0, 6, 0, 8], [0, 16, 0, 18, 0, 14, 0, 16, 0], [16, 0, 16, 0, 32, 0, 16, 0, 16], [0, 16, 0, 14, 0, 18, 0, 16, 0], [8, 0, 6, 0, 16, 0, 10, 0, 8], [0, 14, 0, 16, 0, 16, 0, 18, 0], [6, 0, 8, 0, 16, 0, 8, 0, 10]] writeln("") comment("交点ベクトル v[i] と 隣接行列 A[1] の積") testM("math.multiply(v[1], A[1])") writeln("") comment("隣あう交点ベクトルと 隣接行列 A[1] の積") testM("math.multiply(math.add(v[4], v[5]), A[1])") writeln("") comment("連をなす3交点ベクトルと 隣接行列 A[1] の積") testM("math.multiply(math.add(math.add(v[4], v[5]), v[6]), A[1])") writeln("")