选择行直到rank为N.

时间:2015-01-12 05:26:54

标签: python numpy linear-algebra

我有一个矩阵A(形状(P,Q)),我需要选择一组行I,使得A [I,:]是正方形和可逆的。是否有一种我不知道计算它的算法?

更一般地说,我需要在尽可能多的具有形状(*,Q)的非奇异矩阵中分割A.有算法来计算吗?

一个(指向一个)numpy实现的指针将不胜感激。

我目前的(贪婪和蛮力)实施如下:

def independent_columns_index(A, tol=1e-05):
    """
    Found here: http://stackoverflow.com/questions/13312498/how-to-find-degenerate-rows-columns-in-a-covariance-matrix
    """
    A = np.array(A)
    Q, R = np.linalg.qr(A)
    independent = np.where(np.abs(R.diagonal()) > tol)[0]
    return independent


def independent_rows_index(A, tol=1e-05):
    return independent_columns_index(A.T)


def n_independent_rows_indices(A, n, tol=1e-05):
    if n > A.shape[1]:
        return
    independent = np.empty(0, dtype=int)
    next_unchecked_row = 0
    need_more = n

    while A.shape[0] - next_unchecked_row > need_more:

        need_more = n - len(independent)
        first_row = next_unchecked_row
        last_row = next_unchecked_row + need_more
        next_unchecked_row = last_row

        indices = np.append(independent, np.arange(first_row, last_row))

        subA = A[indices, :]
        ret = independent_rows_index(subA)
        independent = indices[ret]

        if len(independent) == n:
            yield independent
            independent = np.empty(0, dtype=int)

def test():
    A = np.random.randint(0, 100, [43, 5])
    k = 20
    A[-k:, :] = A[:k, :]
    np.random.shuffle(A)
    A[1, :] = A[0, :]
    for ind in n_independent_rows_indices(A, 5):
        R = A[ind, :]
        print(ind)
        print(np.linalg.matrix_rank(R))


if __name__ == '__main__':
    test()
编辑:在Amit的评论之后纠正了问题。在John的评论之后添加了我的天真算法。

编辑:改进的解决方案:

def n_independent_rows_indices(A, n):
    if n > A.shape[1]:
        return

    not_used = np.arange(A.shape[0])
    while True:
        try:
            A_ = np.array(A[not_used, :][:3*n, :]).T
            _, _, P = sp.linalg.qr(A_, pivoting=True)
            now_used = not_used[P[:n]]
            if len(now_used) < n:
                return
            not_used = np.delete(not_used, P[:n], axis=0)
            yield now_used
        except:
            return

0 个答案:

没有答案