Example #1
0
def sparse_xcipy_logdet(A, beta=0):
    xp, xcipy, xsplin = get_array_module(1)
    if not isinstance(
            A,
        (xp.ndarray,
         xcipy.sparse.spmatrix)):  # cupy is installed but A is a cpu array
        xp, xcipy, xsplin = get_array_module(0)
    betaI = beta * xcipy.sparse.eye(A.shape[-1], dtype=A.dtype)
    slu = xsplin.splu(A + betaI)
    ld = xp.log(slu.U.diagonal()).sum()
    return ld.item()
Example #2
0
def test_cheby_op_basis(dtype, device):
    N = 8
    A = torch.rand(N, N, dtype=dtype, device=device)
    A = A + A.t()
    A.fill_diagonal_(0)

    Ats = SparseTensor.from_dense(A)
    xp, xcipy, xsplin = get_array_module(Ats.is_cuda())

    x = torch.ones(N, 1, dtype=dtype, device=device)
    xxp = xp.asarray(x)

    from thgsp.graphs.laplace import laplace as ts_laplace

    Lts = ts_laplace(Ats, "sym")

    krn = np.array([[[meyer_kernel], [meyer_mirror_kernel]]
                    ])  # 1(n_graph) x 2(Cout) x 1(Cin) kernel
    coeff = cheby_coeff(krn, K=6, device=device,
                        dtype=dtype)  # M x Co x Ci x K+1
    yts = cheby_op(x, Lts, coeff[0])
    yts0, yts1 = yts[..., 0]

    c0, c1 = coeff[0].squeeze_()
    H0 = cheby_op_basis(Lts, c0, return_ts=False)
    H1 = cheby_op_basis(Lts, c1, return_ts=True)
    assert H1.dtype() == Lts.dtype()
    assert H1.device() == Lts.device()

    y0 = H0 @ xxp
    y1 = H1 @ x
    err = 1e-5 if dtype is float_dtypes[0] else 1e-12
    assert np.abs(yts0 - y0.ravel()).max() < err
    assert torch.abs(yts1 - y1.ravel()).max() < err
Example #3
0
def test_construct_dia(dt, dv, layout, inverse, narrow):
    on_gpu = "cuda" == dv.type
    xp, xcipy, _ = get_array_module(on_gpu)

    N = 7
    S = [5, 1, 3]
    M = len(S)
    diag_data = xp.arange(N)
    P = construct_dia(S,
                      diag_data=diag_data,
                      ps=narrow,
                      inverse=inverse,
                      dtype=dt,
                      layout=layout)
    if narrow:
        assert P.shape == (M, M)
        if inverse:
            assert xp.allclose(
                P.diagonal(),
                1 / diag_data[S],
            )
        else:
            assert xp.allclose(P.diagonal(), diag_data[S])

    else:
        assert P.shape == (N, N)
        if inverse:
            assert xp.allclose(P.diagonal(), 1 / diag_data)
        else:
            assert xp.allclose(P.diagonal(), diag_data)
Example #4
0
def test_construct_sampling_matrix(dtype, dv, layout):
    on_gpu = "cuda" == dv.type
    xp, xcipy, _ = get_array_module(on_gpu)
    S = [5, 4, 1]
    N = 6
    H = construct_sampling_matrix(N, S, dtype, dv, layout)
    assert H.format == layout
    assert H.shape == (len(S), N)

    D = xcipy.sparse.diags(xp.arange(1, N + 1)[S])
    HtHD0 = H.T @ D @ H
    HtH0 = H.T @ H

    print("\n", H.A)
    print(HtH0.A)
    print(HtHD0.A)
    HtH1 = construct_hth(N, S, dtype=dtype, device=dv, layout=layout)
    HtHD1 = construct_hth(N,
                          S,
                          xp.arange(1, N + 1)[S],
                          dtype=dtype,
                          device=dv,
                          layout=layout)
    # print(HtH1.A)
    # print(HtHD1.A)
    print(type(HtH1), HtH1.shape, "on_gpu: ", on_gpu)
    print(type(HtHD1), HtHD1.shape, "on_gpu: ", on_gpu)
    assert np.allclose(HtH0.A, HtH1.A)
    assert np.allclose(HtHD0.A, HtHD1.A)
Example #5
0
def recon_ess(y, S, U, bd, **kwargs):
    """Naive implementation of ESS sampling reconstruction.

    Parameters
    ----------
    y:  Tensor
        Dense Shape: :obj:`(N)`
    S:  List
        The sampling set
    U:  Tensor
        Dense :obj:`(N, bd)`
    bd: int
        The bandwidth of target signal
    kwargs: dict
        The optional arguments of `xp.linalg.lstsq`
    Returns
    -------
    f_hat:  Tensor
        The reconstructed signal
    """
    assert bd > 1
    assert len(S) > 1
    dv = U.device
    xp, _, _ = get_array_module(U.is_cuda)
    tmp = xp.linalg.lstsq(xp.asarray(U[S, :bd]),
                          xp.asarray(y),
                          **kwargs,
                          rcond=None)[0]
    f_hat = U[:, :bd] @ torch.as_tensor(tmp, device=dv)
    return f_hat
Example #6
0
def recon_bsgda(y,
                S,
                L: SparseTensor,
                mu: float = 0.01,
                reg_order: int = 1,
                **kwargs):
    N = L.size(-1)
    M = len(S)
    assert N >= M > 0
    if y.ndim == 1:
        y = y.view(-1, 1)
    if y.shape[0] != M:
        raise RuntimeError(
            f"y is expected to have a shape ({M},num_signal) or ({M},), not {y.shape}"
        )

    dt, dv, density, on_gpu = get_ddd(L)
    xp, xcipy, xsplin = get_array_module(on_gpu)

    L = to_xcipy(L)
    Ht = construct_sampling_matrix(N, S, dtype=dt, device=dv, layout="csr").T
    HtH = construct_hth(N, S, dtype=dt, device=dv, layout="csr")
    B = HtH + mu * L**reg_order
    Hty = Ht @ xp.asarray(y)

    if xp == np:
        x_hat = xsplin.spsolve(B, Hty, **kwargs)
    else:
        num_sig = Hty.shape[-1]
        x_hat = xp.empty((N, num_sig), dtype=Hty.dtype)
        for j in range(num_sig):
            x_hat[:, j] = xsplin.spsolve(B, Hty[:, j], **kwargs)
    return torch.as_tensor(x_hat, device=dv)
Example #7
0
def cheby_op_basis(L, coeff, lam_max=2.0, return_ts=False):
    assert coeff.ndim == 1
    K = len(coeff)
    if isinstance(L, SparseTensor):
        dt, dv, density, on_gpu = get_ddd(L)
        xp, xcipy, _ = get_array_module(on_gpu)
    elif isinstance(L, spmatrix):
        import scipy

        xcipy = scipy
        xp = np
    else:
        raise TypeError

    L = to_xcipy(L)
    N = L.shape[-1]

    coeff = xp.asarray(coeff)
    Im = xcipy.sparse.eye(N, dtype=L.dtype, format="csr")

    Ln = L * (2 / lam_max) - Im
    Tl_old = Im
    Tl_cur = Ln
    Hl = 0.5 * coeff[0] * Tl_old + coeff[1] * Tl_cur
    for k in range(2, K):
        Tl_new = 2 * Ln * Tl_cur - Tl_old
        Hl = Hl + coeff[k] * Tl_new
        Tl_old = Tl_cur
        Tl_cur = Tl_new

    if return_ts:
        result = SparseTensor.from_scipy(Hl) if xp == np else from_cpx(Hl)
    else:
        result = Hl
    return result
Example #8
0
def test_get_array_module(on_gpu):
    xp, xcipy, _ = get_array_module(on_gpu=on_gpu)
    if on_gpu:
        try:
            import cupy as cp
            import cupyx.scipy as xscipy

            assert xp == cp
            assert xscipy == xscipy
        except ImportError:
            pytest.skip("CuPy is not installed, use numpy and scipy instead")

    else:
        assert xp == np
        assert xcipy == scipy
Example #9
0
def recon_rsbs(y,
               S,
               L: SparseTensor,
               cum_coh,
               mu: float = 0.01,
               reg_order: int = 1,
               **kwargs):
    N = L.size(-1)
    M = len(S)
    assert M > 0
    if y.shape[0] != M:
        raise RuntimeError(
            f"y is expected to have a shape ({M},num_signal) or ({M},), not {y.shape}"
        )

    dt, dv, density, on_gpu = get_ddd(L)
    xp, xcipy, xsplin = get_array_module(on_gpu)

    yp = to_xp(y).astype("d")

    L = to_xcipy(L, layout="csr").astype("d")
    H = construct_sampling_matrix(N, S, torch.double, dv)
    Psinv = construct_dia(S,
                          cum_coh,
                          ps=True,
                          inverse=True,
                          dtype=torch.double,
                          device=dv)

    Bl = H.T * Psinv
    B = Bl * H + mu * L**reg_order

    HPy = Bl @ yp

    if xp == np:
        x_hat = xsplin.spsolve(B, HPy, **kwargs)
    else:
        num_sig = yp.shape[-1]
        x_hat = xp.empty((N, num_sig), dtype=yp.dtype)
        for j in range(num_sig):
            x_hat[:, j] = xsplin.spsolve(B, HPy[:, j], **kwargs)

    return torch.as_tensor(x_hat, device=dv)
Example #10
0
def recon_fastssss(y, S, T, order, sd=0.5):
    """A primary implementation of reconstruction method associated with
    "FastSSS" sampling algorithm.

    Parameters
    ----------
    y:  Tensor
        The measurements on sampling set :obj:S:. If the localization operator :obj:`T`
        has a density greater than the threshold :obj:`sd`, :obj:`y` has a shape of
        either :obj:`(M,)`,:obj:`(M,1)`,or :obj:`(M,C)`; otherwise :obj:`y` could only
        be  either :obj:`(M,)` or :obj:`(M,1)`.
    S:  List
        A list consisting of all indices of sampled nodes.
    T:  Tensor, SparseTensor
        The localization operator
    order: int
    sd: float
        The threshold of :obj:`T`'s density that controls when we use a dense or sparse
        linear solver.

    Returns
    -------
    Tensor
        The signal recovered from the measurements :obj:`y` .
    """
    T_k = matrix_power(T, order)
    dt, dv, density, on_gpu = get_ddd(T_k)
    if density > sd:
        T_k = T_k.to_dense()
        tmp = torch.linalg.solve(T_k[np.ix_(S, S)], torch.as_tensor(y))
        x_hat = T_k[:, S] @ tmp

    else:
        T_k = to_xcipy(T_k)
        xp, xcipy, xsplin = get_array_module(on_gpu)
        tmp = xsplin.spsolve(T_k[xp.ix_(S, S)], xp.asarray(y))
        x_hat = T_k[:, S] * tmp
    return torch.as_tensor(x_hat, device=dv)