2016年8月5日金曜日

学習環境/開発環境

線型代数入門 (松坂 和夫(著)、岩波書店)の第3章(線型写像)、7(行列の積)、問11.を取り組んでみる。

問11.

BA=( c 11 c 1( n 1 + n 2 ) c ( l 1 + l 2 )1 c ( l 1 + l 2 )( n 1 + n 2 ) )=( C 11 C 12 C 21 C 22 ) C 11 1i l 1 ,1j n 1 c ij = j'=1 m 1 + m 2 b ij' a j'j = j'=1 m 1 b i j a j'j + j'= m 1 +1 m 2 b ij' a j j C 11 = B 11 A 11 + B 12 A 21 C 12 = B 11 A 12 + B 12 A 22 C 21 = B 21 A 11 + B 22 A 21 C 22 = B 21 A 12 + B 22 A 22 BA=( B 11 A 11 + B 12 A 21 B 11 A 12 + B 12 A 22 B 21 A 11 + B 22 A 21 B 21 A 12 + B 22 A 22 )

JavaScript

コード(Emacs)

// matrix.js
var Matrix;

Matrix = function (m, n, fill) {
    var fill = fill || 0,
        m = m,
        n = n,
        matrix = [],
        i,
        j,
        row;

    for (i = 0; i < m; i += 1) {
        row = [];
        for (j = 0; j < n; j += 1) {
            row.push(fill);
        }
        matrix.push(row);
    }
    this.rowLength = function () {
        return m;
    };
    this.colomnLength = function () {
        return n;
    };
    this.getElement = function (i, j) {
        this.isValidIndex(m, n, i, j);
        return matrix[i-1][j-1];
    };
    this.setElement = function (i, j, elem) {
        this.isValidIndex(m, n, i, j);
        matrix[i-1][j-1] = elem;
    };
};
Matrix.prototype.isValidIndex = function (m, n, i, j) {
    if (i < 1 || m < i || j < 1 || n < j) {
        throw {
            type: 'Index error',
            message: m + ' x ' + n + ': ' + '(' + i + ', ' + j + ')'
        };
    }
};
Matrix.prototype.toArray = function () {
    var matrix = [],
        i,
        j,
        m = this.rowLength(),
        n = this.colomnLength(),
        row;

    for (i = 1; i <= m; i += 1) {
        row = [];
        for (j = 1; j <= n; j += 1) {
            row.push(this.getElement(i, j))
        }
        matrix.push(row);
    }
    return matrix;
};
Matrix.prototype.toString = function () {
    var m = this.rowLength(),
        n = this.colomnLength(),
        i,
        j,
        result = '<math><mfenced><mtable>';

    if (typeof window !== 'undefined') {
        for (i = 1; i <= m; i += 1) {
            result += '<mtr>';
            for (j = 1; j <= n; j += 1) {
                result += '<mtd><mn>' + this.getElement(i, j) + '</mn></mtd>';
            }
            result += '</mtr>';
        }
        result += '</mtable></math>';
        return result;
    }
    return this.toArray();
};
Matrix.prototype.getRow = function (i) {
    var j,
        n = this.colomnLength(),
        row = new Matrix(1, n);

    for (j = 1; j <= n; j += 1) {
        row.setElement(1, j, this.getElement(i, j));
    }
    return row;
};
Matrix.prototype.getColomn = function (j) {
    var m = this.rowLength(),
        i,
        col = new Matrix(m, 1);

    for (i = 1; i <= m; i += 1) {
        col.setElement(i, 1, this.getElement(i, j));
    }
    return col;
};
Matrix.prototype.setRow = function (i, row) {
    var n = this.colomnLength(),
        j;
    
    for (j = 1; j <= n; j += 1) {
        this.setElement(i, j, row.getElement(1, j));
    }
};
Matrix.prototype.setColomn = function (j, colomn) {
    var m = this.rowLength(),
        i;
    
    for (i = 1; i <= m; i += 1) {
        this.setElement(i, j, colomn.getElement(i, 1));
    }
};
Matrix.prototype.isEqual = function (mat) {
    var m = this.rowLength(),
        n = this.colomnLength(),
        i,
        j;

    if (m !== mat.rowLength() || n !== mat.colomnLength()) {
        return false;
    }
    for (i = 1; i <= m; i += 1) {
        for (j = 1; j <= n; j += 1) {
            if (this.getElement(i, j) !== mat.getElement(i, j)) {
                return false;
            }
        }
    }
    return true;
};
Matrix.prototype.add = function (mat) {
    var m = this.rowLength(),
        n = this.colomnLength(),
        matrix = new Matrix(m, n),
        i,
        j;

    for (i = 1; i <= m; i += 1) {
        for (j = 1; j <= n; j += 1) {
            matrix.setElement(i, j,
                              this.getElement(i, j) + mat.getElement(i, j));
        }
    }
    return matrix;
};
Matrix.prototype.mulMatrix = function (mat) {
    var m = this.rowLength(),
        n = this.colomnLength(),
        m0 = mat.rowLength(),
        n0 = mat.colomnLength(),
        i,
        j,
        matrix = new Matrix(m, n0),
        elem,
        j0;

    if (n !== m0) {
        throw {
            type: "mulMatrix error",
            message: '(' + m + ', ' + n + ') x (' + m0 + ', ' + n0 + ')',
        };
    }
    for (i = 1; i <= m; i += 1) {
        for (j = 1; j <= n0; j += 1) {
            elem = 0;
            for (j0 = 1; j0 <= n; j0 += 1) {
                elem += this.getElement(i, j0) * mat.getElement(j0, j);
            }
            matrix.setElement(i, j, elem);
        }
    }
    return matrix;
};
Matrix.prototype.mulScalar = function (scalar) {
    var m = this.rowLength(),
        n = this.colomnLength(),
        i,
        j,
        matrix = new Matrix(m, n);

    for (i = 1; i <= m; i += 1) {
        for (j = 1; j <= n; j += 1) {
            matrix.setElement(i, j, this.getElement(i, j) * scalar);
        }
    }
    return matrix;
};
Matrix.prototype.transposed = function () {
    var m = this.colomnLength(),
        n = this.rowLength(),
        i,
        j,
        matrix = new Matrix(m, n);

    for (i = 1; i <= m; i += 1) {
        for (j = 1; j <= n; j += 1) {
            matrix.setElement(i, j, this.getElement(j, i));
        }
    }
    return matrix;
};
Matrix.prototype.isSquare = function () {
    return this.rowLength() === this.colomnLength();
};
Matrix.prototype.trace = function () {
    var out = 0,
        n = this.rowLength(),
        i;

    if (this.isSquare()) {
        for (i = 1; i <= n; i += 1) {
            out += this.getElement(i, i);
        }
        return out;
    }
    throw {
        type: 'trace error',
        message: this + ' not a Square Matrix',
    };
};
Matrix.prototype.det = function () {
    var n,
        i,
        k,
        i0,
        j0,
        i1,
        j1,
        result,
        matrix;
    
    if (this.isSquare()) {        
        n = this.rowLength();
        if (n === 1) {
            return this.getElement(n, n);
        }
        k = Math.floor(Math.random() * n) + 1;
        result = 0;
        for (i = 1; i <= n; i += 1) {
            matrix = new Matrix(n - 1, n - 1);            
            for (i0 = 1, i1 = 1; i0 <= n; i0 += 1) {
                if (i0 === i) {
                    continue;
                }
                for (j0 = 1, j1 = 1; j0 <= n; j0 += 1) {
                    if (j0 === k) {
                        continue;
                    }
                    matrix.setElement(i1, j1, this.getElement(i0, j0));
                    j1 += 1;
                }
                i1 += 1;
            }
            result +=
                Math.pow(-1, i + k) * this.getElement(i, k) * matrix.det();
        }
        return result;
    }
    throw {
        type: 'det error',
        message: this + ' not a Square Matrix'
    };
};
Matrix.prototype.isRegular = function () {
    if (!this.isSquare()) {
        throw {
            type: 'isRegular error',
            message: this + ' not a Square Matrix',
        }
    }
    return this.det() !== 0;
};
Matrix.prototype.adjoint = function () {
    var n,
        i,
        j,
        i0,
        j0,
        i1,
        j1,
        matrix0,
        matrix1;
    
    if (this.isSquare()) {
        n = this.rowLength();
        matrix0 = new Matrix(n - 1, n - 1);
        matrix1 = new Matrix(n, n);        
        for (i = 1; i <= n; i += 1) {            
            for (j = 1; j <= n; j += 1) {
                for (i0 = 1, i1 = 1; i1 <= n; i1 += 1) {
                    if (i1 === i) {
                        continue;
                    }
                    for (j0 = 1, j1 = 1; j1 <= n; j1 += 1) {
                        if (j1 === j) {
                            continue;
                        }
                        matrix0.setElement(i0, j0, this.getElement(i1, j1));
                        j0 += 1;
                    }
                    i0 += 1;
                }
                matrix1.setElement(j, i, Math.pow(-1, i + j) * matrix0.det());
            }
        }
        return matrix1;
    }    
    throw {
        type: 'isRegular error',
        message: this + ' not a Square Matrix',
    }        
    
};
Matrix.prototype.inverse = function () {
    if (!this.isSquare()) {
        throw {
            type: 'inverse error',
            message: this + ' not a Square Matrix',
        };
    }
    if (!this.isRegular()) {
        throw {
            type: 'inverse error',
            message: this + ' is a Irregular Matrix',
        };
    }
    return this.adjoint().mulScalar(1 / this.det());
};
Array.prototype.toRow = function () {
    var len = this.length,
        matrix = new Matrix(1, len),
        j;

    for (j = 1; j <= len; j += 1) {
        matrix.setElement(1, j, this[j - 1]);
    }
    return matrix;
};
Array.prototype.toColomn = function () {
    var len = this.length,
        matrix = new Matrix(len, 1),
        i;

    for (i = 1; i <= len; i += 1) {
        matrix.setElement(i, 1, this[i - 1]);
    }
    return matrix;
};
Array.prototype.toMatrix = function () {
    var m = this.length,
        n = this[0].length,
        matrix = new Matrix(m, n),
        i,
        j;

    for (i = 1; i <= m; i += 1) {
        for (j = 1; j <= n; j += 1) {
            matrix.setElement(i, j, this[i-1][j-1]);
        }
    }
    return matrix;
};

// test
var a = [],
    m = [],
    n = [],
    b = [],
    l = [],
    i_ary = [1, 2],
    j_ary = [1, 2],
    a_mat,
    b_mat,
    mat,
    row,
    col,
    c = [],
    c_mat,                      // BA
    answer0 = document.querySelector('#answer0'),
    result = '',
    nl = '<br>';

i_ary.forEach(function (i) {
    m[i] = Math.floor(Math.random() * 5) + 1;
});
j_ary.forEach(function (j) {
    n[j] = Math.floor(Math.random() * 5) + 1;
});
i_ary.forEach(function (i) {
    l[i] = Math.floor(Math.random() * 5) + 1;;
});

// Aij, Bij
i_ary.forEach(function (i) {
    a[i] = [];
    b[i] = [];
    j_ary.forEach(function (j) {
        mat = new Matrix(m[i], n[j]);
        for (row = 1; row <= m[i]; row += 1) {
            for (col = 1; col <= n[j]; col += 1) {
                mat.setElement(row, col, Math.floor(Math.random()* 10));
            }
        }
        a[i][j] = mat;
        mat = new Matrix(l[i], m[j]);
        for (row = 1; row <= l[i]; row += 1) {
            for (col = 1; col <= m[j]; col += 1) {
                mat.setElement(row, col, Math.floor(Math.random() * 10));
            }
        }
        b[i][j] = mat;
    });
});

a_mat = new Matrix(m[1] + m[2], n[1] + n[2]);
for (row = 1; row <= m[1] + m[2]; row += 1) {
    for (col = 1; col <= n[1] + n[2]; col += 1) {
        if (row <= m[1]) {
            if (col <= n[1]) {
                a_mat.setElement(row, col, a[1][1].getElement(row, col));
            } else {
                a_mat.setElement(row, col, a[1][2].getElement(row, col - n[1]));
            }
        } else {
            if (col <= n[1]) {
                a_mat.setElement(row, col, a[2][1].getElement(row - m[1],
                                                              col));
            } else {
                a_mat.setElement(row, col, a[2][2].getElement(row - m[1],
                                                              col - n[1]));
            }
        }
    }
}
b_mat = new Matrix(l[1] + l[2], m[1] + m[2]);
for (row = 1; row <= l[1] + l[2]; row += 1) {
    for (col = 1; col <= m[1] + m[2]; col += 1) {
        if (row <= l[1]) {
            if (col <= m[1]) {
                b_mat.setElement(row, col, b[1][1].getElement(row, col));
            } else {
                b_mat.setElement(row, col, b[1][2].getElement(row, col - m[1]));
            }
        } else {
            if (col <= m[1]) {
                b_mat.setElement(row, col, b[2][1].getElement(row - l[1],
                                                              col));
            } else {
                b_mat.setElement(row, col, b[2][2].getElement(row - l[1],
                                                              col - m[1]));
            }
        }
    }
}

i_ary.forEach(function (i) {
    c[i] = []
    j_ary.forEach(function (j) {
        c[i][j] = b[i][1].mulMatrix(a[1][j])
            .add(b[i][2].mulMatrix(a[2][j]));
    });
});

c_mat = b_mat.mulMatrix(a_mat);

result += 'B =' + nl;
i_ary.forEach(function (i) {
    j_ary.forEach(function (j) {
        result += b[i][j];
    });
    result += nl;
});
result += nl;
result += 'A =' + nl;
i_ary.forEach(function (i) {
    j_ary.forEach(function (j) {
        result += a[i][j];
    });
    result += nl;
});
result += nl + 'BA = ' + b_mat + a_mat + nl + nl;

result += 'C =' + nl;
i_ary.forEach(function (i) {
    j_ary.forEach(function (j) {
        result += c[i][j];
    });
    result += nl;
});
result += nl + ' = ' + c_mat + nl + nl;

if (b_mat.mulMatrix(a_mat).isEqual(c_mat)) {
    result += 'BA = C'
} else {
    result += 'BA /= C';
}
answer0.innerHTML = result;

0 コメント:

コメントを投稿