Exemplo n.º 1
0
 def test_matrix_multiply(self):
     matrix1 = Matrix.from_cols([[1, 2], [3, 4], [5, 6]])
     matrix2 = Matrix.from_cols([[1, 2, 3], [4, 5, 6]])
     product = matrix1.multiply(matrix2)
     assert product.size() == (2, 2)
     assert product.all_cols() == [[22, 28], [49, 64]]
     product = matrix2.multiply(matrix1)
     assert product.size() == (3, 3)
     assert product.all_cols() == [[9, 12, 15], [19, 26, 33], [29, 40, 51]]
Exemplo n.º 2
0
 def test_lu_more_rows(self):
     mat_l = Matrix.from_cols([[1, 2, 3, 4, 5], [0, 1, 2, 3, 4],
                               [0, 0, 1, 2, 3], [0, 0, 0, 1, 2],
                               [0, 0, 0, 0, 1]])
     mat_u = Matrix.from_cols([[5, 1, 2, 3, 4], [0, 4, 3, 2, 1],
                               [0, 0, 2, 1, 0]])
     matrix = mat_l.multiply(mat_u)
     mat_l, mat_u = compute_lu_factorization(matrix)
     # note LU factorization is not unique therefore we are not comparing L and U
     utils.assert_lower_triangular(mat_l)
     utils.assert_upper_triangular(mat_u)
     assert self.vector_all(utils.extract_diagonal(mat_l), 1)
     product = mat_l.multiply(mat_u)
     assert product.all_cols() == matrix.all_cols()
Exemplo n.º 3
0
 def test_reduce_to_bidiagonal(self):
     mat = Matrix.from_cols([[1, 2, 3], [4, 5, 6], [7, 8, 10]])
     b, _, _ = reduce_to_bidiagonal(mat)
     utils.assert_upper_triangular(b)
     truncated = MatrixView.with_size(
         b, (0, 1), (mat.num_rows() - 1, mat.num_cols() - 1)).to_matrix()
     utils.assert_lower_triangular(truncated)
Exemplo n.º 4
0
 def test_create_from_cols(self):
     matrix = Matrix.from_cols([[1, 2], [3, 4], [5, 6]])
     assert matrix.size() == (2, 3)
     assert matrix.get_col(0) == [1, 2]
     assert matrix.get_col(1) == [3, 4]
     assert matrix.get_col(2) == [5, 6]
     assert matrix.get_row(0) == [1, 3, 5]
     assert matrix.get_row(1) == [2, 4, 6]
Exemplo n.º 5
0
 def test_lu(self):
     matrix = Matrix.from_cols([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
     mat_l, mat_u = compute_lu_factorization(matrix)
     utils.assert_lower_triangular(mat_l)
     utils.assert_upper_triangular(mat_u)
     assert self.vector_all(utils.extract_diagonal(mat_l), 1)
     product = mat_l.multiply(mat_u)
     assert product.all_cols() == matrix.all_cols()
Exemplo n.º 6
0
 def test_bidiagonal_recreate_2(self):
     mat = Matrix.from_cols([[1, 2, 3], [2, 5, 1], [-1, 3, -2]])
     b, left, right = reduce_to_bidiagonal(mat)
     for index, hh in list(enumerate(left))[::-1]:
         b = hh.multiply_left(b, index)
     for index, hh in list(enumerate(right))[::-1]:
         b = hh.multiply_right(b, index + 1)
     utils.assert_matrix_equal(mat, b)
Exemplo n.º 7
0
 def test_givens_rotation(self):
     givens = Givens(1, 1)
     product = givens.multiply_left(Matrix.from_cols([[1, 1]]))
     assert product.size() == (2, 1)
     assert product.get_col(0) == pytest.approx([math.sqrt(2), 0])
     product = givens.multiply_left_column([1, 1])
     assert product.size() == (2, 1)
     assert product.get_col(0) == pytest.approx([math.sqrt(2), 0])
Exemplo n.º 8
0
 def test_householder_col(self):
     vec = [5, 4, 3, 2, 1]
     householder = Householder(vec)
     vec_as_mat = Matrix.from_cols([vec])
     product = householder.multiply_left(vec_as_mat)
     assert product.num_cols() == 1
     assert product.get(0, 0) == pytest.approx(vec_as_mat.frobenius_norm())
     for elem in product.get_col(0)[1:]:
         assert elem == pytest.approx(0)
Exemplo n.º 9
0
 def test_householder_row(self):
     vec = [5, 4, 3, 2, 1]
     householder = Householder(vec)
     row_matrix = Matrix.from_rows([vec])
     product = householder.multiply_right(row_matrix)
     assert product.num_rows() == 1
     assert product.get(0, 0) == pytest.approx(row_matrix.frobenius_norm())
     for elem in product.get_row(0)[1:]:
         assert elem == pytest.approx(0)
Exemplo n.º 10
0
 def test_matrix_transpose(self):
     matrix = Matrix.from_cols([[1, 2], [3, 4], [5, 6]])
     mat_transpose = matrix.transpose()
     assert matrix.num_rows() == mat_transpose.num_cols()
     assert matrix.num_cols() == mat_transpose.num_rows()
     for i in range(matrix.num_rows()):
         assert matrix.get_row(i) == mat_transpose.get_col(i)
     for i in range(matrix.num_cols()):
         assert matrix.get_col(i) == mat_transpose.get_row(i)
Exemplo n.º 11
0
def compute_qr_factorization(mat: Matrix) -> (Matrix, Matrix):
    # Do not overwrite original matrix
    mat = mat.copy()
    householders = []  # store householder transformations
    iterations = min(mat.num_rows(), mat.num_cols())
    for iteration in range(iterations):
        col = mat.get_col(iteration)
        # Zero out the entries below the diagonal
        hh = Householder(col[iteration:])
        householders.append((iteration, hh))
        mat = hh.multiply_left(mat, pad_top=iteration)
    # Accumulate the householder transformations
    q_mat = Matrix.identity(mat.num_rows())
    for iteration, hh in householders[::-1]:
        q_mat = hh.multiply_left(q_mat, pad_top=iteration)
    return (q_mat, mat)
Exemplo n.º 12
0
def reduce_to_bidiagonal(
        mat: Matrix) -> (Matrix, List[Householder], List[Householder]):
    mat = mat.copy()
    if mat.num_rows() != mat.num_cols():
        raise ValueError("Matrix should be square")
    iterations = mat.num_rows() - 1
    acc_left = []
    acc_right = []
    for iteration in range(iterations):
        # clear zeroes below diagonal
        col = mat.get_col(iteration)[iteration:]
        householder_left = Householder(col)
        mat = householder_left.multiply_left(mat, pad_top=iteration)
        acc_left.append(householder_left)
        if iteration != iterations - 1:
            # clear zeroes above superdiagonal
            row = mat.get_row(iteration)[iteration + 1:]
            householder_right = Householder(row)
            mat = householder_right.multiply_right(mat, pad_top=iteration + 1)
            acc_right.append(householder_right)
    return mat, acc_left, acc_right
Exemplo n.º 13
0
 def test_rectangular_triangular(self):
     utils.assert_upper_triangular(
         Matrix.from_cols([[4, 0], [1, 2], [3, 4]]))
Exemplo n.º 14
0
 def test_identity_triangular(self):
     identity = Matrix.identity(3)
     utils.assert_upper_triangular(identity)
     utils.assert_lower_triangular(identity)
Exemplo n.º 15
0
 def test_upper_triangular(self):
     mat = Matrix.from_cols([[1, 0, 0], [2, 3, 0], [4, 5, 6]])
     utils.assert_upper_triangular(mat)
     with pytest.raises(AssertionError):
         utils.assert_upper_triangular(mat.transpose())
Exemplo n.º 16
0
def compute_svd(mat: Matrix) -> (Matrix, Matrix, Matrix):
    if mat.num_cols() > mat.num_rows():
        u, s, v = compute_svd(mat.transpose())
        return v, s.transpose(), u
    elif mat.num_rows() > mat.num_cols():
        # mat is m x n, m > n
        # q should be m x m, r should be m x n
        q, r = compute_qr_factorization(mat)
        # truncate r to be n x n, truncate q to be m x n
        r_truncated = MatrixView.with_size(
            r, (0, 0), (mat.num_cols(), mat.num_cols())).to_matrix()
        u, s, v = compute_svd(r_truncated)
        u_padded = Matrix.identity(mat.num_rows())
        MatrixView.with_size(u_padded, (0, 0),
                             (mat.num_cols(), mat.num_cols())).set(
                                 MatrixView.whole(u))
        u = q.multiply(u_padded)
        s_padded = Matrix.zeroes(mat.num_rows(), mat.num_cols())
        MatrixView.with_size(s_padded, (0, 0),
                             (mat.num_cols(), mat.num_cols())).set(
                                 MatrixView.whole(s))
        s = s_padded
        return u, s, v
    else:
        # matrix is square
        b, left, right = reduce_to_bidiagonal(mat)
        u, s, v = compute_svd_bidiagonal(b)
        for index, hh in list(enumerate(left))[::-1]:
            u = hh.multiply_left(u, index)
        v_transpose = v.transpose()
        for index, hh in list(enumerate(right))[::-1]:
            v_transpose = hh.multiply_right(v_transpose, index + 1)
        return u, s, v_transpose.transpose()
Exemplo n.º 17
0
 def test_svd_bidiagonal(self):
     mat = Matrix.from_cols([[1, 0, 0], [2, 3, 0], [0, 4, 5]])
     u, s, v = compute_svd_bidiagonal(mat)
     self.check_svd(u, s, v, mat)
Exemplo n.º 18
0
 def test_householder_inverse(self):
     vec = [5, 4, 3, 2, 1]
     householder = Householder(vec)
     householder_mat = householder.to_matrix()
     product = householder_mat.multiply(householder_mat)
     utils.assert_matrix_equal(product, Matrix.identity(5))
Exemplo n.º 19
0
 def test_givens_matrix(self):
     givens = Givens(1, 1).to_matrix()
     product = givens.multiply(Matrix.from_cols([[1, 1]]))
     assert product.size() == (2, 1)
     assert product.get_col(0) == pytest.approx([math.sqrt(2), 0])
Exemplo n.º 20
0
 def test_svd_more_cols(self):
     mat = Matrix.from_cols([[1, 2, 3], [2, 5, 1], [-1, 3, -2], [3, 2, 1]])
     u, s, v = compute_svd(mat)
     self.check_svd(u, s, v, mat)
Exemplo n.º 21
0
 def test_create_fail(self):
     with pytest.raises(ValueError):
         Matrix.from_cols([[1, 2], [3], [5, 6]])
     with pytest.raises(ValueError):
         Matrix.from_rows([[1, 2], [3, 4], [6]])
Exemplo n.º 22
0
 def test_matrix_multiply_fail(self):
     matrix1 = Matrix.from_cols([[1, 2], [3, 4], [5, 6]])
     with pytest.raises(ValueError):
         matrix1.multiply(matrix1)
Exemplo n.º 23
0
 def test_identity(self):
     identity = Matrix.identity(3)
     assert identity.all_cols() == [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
Exemplo n.º 24
0
def generate_matrix_normal(size: int) -> Matrix:
    columns = [[generate_normal() for _ in range(size)] for _ in range(size)]
    return Matrix.from_cols(columns)
Exemplo n.º 25
0
 def test_givens_padded(self):
     givens = Givens(-0.8, 0.6)
     product = givens.multiply_left(Matrix.from_cols([[1, 2, -0.8, 0.6]]),
                                    2)
     assert product.size() == (4, 1)
     assert product.get_col(0) == pytest.approx([1, 2, 1, 0])
Exemplo n.º 26
0
 def test_lower_triangular(self):
     mat = Matrix.from_cols([[1, 2, 3], [0, 4, 5], [0, 0, 6]])
     utils.assert_lower_triangular(mat)
     with pytest.raises(AssertionError):
         utils.assert_lower_triangular(mat.transpose())
Exemplo n.º 27
0
 def test_svd_bidiagonal_2(self):
     mat = Matrix.from_cols([[3.742, 0, 0], [4.018, 3.511, 0],
                             [0, -3.408, -1.979]])
     u, s, v = compute_svd_bidiagonal(mat)
     self.check_svd(u, s, v, mat)
Exemplo n.º 28
0
def compute_svd_bidiagonal(mat: Matrix) -> (Matrix, Matrix, Matrix):
    dims = mat.num_cols()
    u = Matrix.identity(dims)
    v = Matrix.identity(dims)
    while True:
        # while not converged
        # find max off-diagonal
        max_off_diag = 0
        diag_sum = 0
        for i in range(dims - 1):
            max_off_diag = max(max_off_diag, abs(mat.get(i, i + 1)))
        for i in range(dims):
            diag_sum += abs(mat.get(i, i))
        diag_sum /= dims
        if max_off_diag < diag_sum * 1e-6 and max_off_diag < 1e-8:
            break

        # introduce the bulge
        givens = Givens(
            mat.get(0, 0)**2 - mat.get(dims - 1, dims - 1)**2 -
            mat.get(dims - 2, dims - 1)**2,
            mat.get(0, 1) * mat.get(0, 0)).transpose()
        mat = givens.multiply_right(mat)
        v = givens.transpose().multiply_left(v)

        # chase the bulge
        for iteration in range(0, dims - 1):
            # zero subdiagonal
            givens_lower = Givens(mat.get(iteration, iteration),
                                  mat.get(iteration + 1, iteration))
            mat = givens_lower.multiply_left(mat, pad_top=iteration)
            u = givens_lower.transpose().multiply_right(u, pad_top=iteration)
            # zero above superdiagonal
            if iteration != dims - 2:
                givens_upper = Givens(mat.get(iteration, iteration + 1),
                                      mat.get(iteration,
                                              iteration + 2)).transpose()
                mat = givens_upper.multiply_right(mat, pad_top=iteration + 1)
                v = givens_upper.transpose().multiply_left(v,
                                                           pad_top=iteration +
                                                           1)

    v = v.transpose()
    # Ensure singular values are non-negative
    for i in range(dims):
        if mat.get(i, i) < 0:
            MatrixView.with_size(mat, (i, i), (1, 1)).scale(-1)
            MatrixView(u, (0, i), (u.num_rows() - 1, i)).scale(-1)

    # reorder columns
    sv = [(mat.get(i, i), i) for i in range(dims)]
    sv.sort()
    sv = sv[::-1]
    sorted_v_cols = [v.get_col(index) for value, index in sv]
    sorted_u_cols = [u.get_col(index) for value, index in sv]
    v = Matrix.from_cols(sorted_v_cols)
    u = Matrix.from_cols(sorted_u_cols)
    mat = Matrix.zeroes(dims, dims)
    for index, (value, _) in enumerate(sv):
        MatrixView.with_size(mat, (index, index),
                             (1, 1)).set_element(0, 0, value)

    return u, mat, v
Exemplo n.º 29
0
 def test_givens_inverse(self):
     givens = Givens(1, 1).to_matrix()
     product = givens.transpose().multiply(givens)
     utils.assert_matrix_equal(product, Matrix.identity(2))