Example #1
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 #2
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 #3
0
def construct_hth(N,
                  S,
                  D=None,
                  dtype=None,
                  device=None,
                  layout="csr",
                  return_ts=False):
    M = len(S)
    row = torch.as_tensor(S, device=device)
    col = row.clone()
    data = torch.ones(M, dtype=dtype, device=device)
    if D is not None:
        data = data * torch.as_tensor(D, dtype=dtype, device=device)

    spa = SparseTensor(row=row, col=col, value=data, sparse_sizes=(N, N))
    HtH = spa if return_ts else to_xcipy(spa, layout)
    return HtH
Example #4
0
def construct_sampling_matrix(N,
                              S,
                              dtype=None,
                              device=None,
                              layout="csr",
                              return_ts=False):
    r"""
    Construct the sampling matrix :math:`\mathbf{H} \in\{0,1\}^{M \times N}` defined as
    follows.

    .. math::
       \mathbf{H}_{i j}= \begin{cases}1, & j=\mathcal{S}_{i} \\ 0, & \text { otherwise }
       \end{cases}


    Parameters
    ----------
    N: int
        The total number of nodes
    S:  list, array, torch.Tensor
        The 1-D list of sampled nodes.
    dtype: torch.dtype, optional
        The dtype
    layout: str
        The memory layout of the generated sparse matrix. One of ("csc", "csr", "coo").
    device: torch.device, str, optional
        If `True` and `cupy` is installed, use `cupy`as backend; otherwise `scipy`.
    return_ts: bool,
        If False, return `scipy.sparse.spmatrix` of device is GPU else
        'cupyx.scipy.sparse.spmatrix'

    Returns
    -------
    H: spmatrix
        The :obj:`(M,N)` scipy sparse matrix with :obj:`layout` format

    """
    M = len(S)
    row = torch.arange(M, device=device)
    col = torch.as_tensor(S, device=device)
    data = torch.ones(M, dtype=dtype, device=device)

    spa = SparseTensor(row=row, col=col, value=data, sparse_sizes=(M, N))
    H = spa if return_ts else to_xcipy(spa, layout)
    return H
Example #5
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 #6
0
def construct_dia(
    S,
    diag_data,
    ps=True,
    inverse=False,
    dtype=None,
    device=None,
    layout="csr",
    return_ts=False,
):
    N = len(diag_data)
    M = len(S)
    row = torch.arange(M, device=device) if ps else torch.arange(N,
                                                                 device=device)
    col = row.clone()
    shape = (M, M) if ps else (N, N)
    data = torch.as_tensor(diag_data, dtype=dtype, device=device)
    data = data**-1 if inverse else data
    data = data[S] if ps else data
    spa = SparseTensor(row=row, col=col, value=data, sparse_sizes=shape)
    P = spa if return_ts else to_xcipy(spa, layout)
    return P
Example #7
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)
Example #8
0
def test_to_xcipy(device, layout):
    spa = SparseTensor.from_dense(torch.rand(3, 3, device=device))
    xcia = to_xcipy(spa, layout=layout)
    assert xcia.shape == (3, 3)
    assert xcia.format == layout