예제 #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]]
예제 #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()
예제 #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)
예제 #4
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)
예제 #5
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])
예제 #6
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]
예제 #7
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()
예제 #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)
예제 #9
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)
예제 #10
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())
예제 #11
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)
예제 #12
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]])
예제 #13
0
 def test_matrix_multiply_fail(self):
     matrix1 = Matrix.from_cols([[1, 2], [3, 4], [5, 6]])
     with pytest.raises(ValueError):
         matrix1.multiply(matrix1)
예제 #14
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)
예제 #15
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)
예제 #16
0
 def test_rectangular_triangular(self):
     utils.assert_upper_triangular(
         Matrix.from_cols([[4, 0], [1, 2], [3, 4]]))
예제 #17
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])
예제 #18
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])
예제 #19
0
def generate_matrix_normal(size: int) -> Matrix:
    columns = [[generate_normal() for _ in range(size)] for _ in range(size)]
    return Matrix.from_cols(columns)
예제 #20
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())
예제 #21
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